Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
TCloud_Document
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
chenjunxiong
TCloud_Document
Commits
dbf35503
Commit
dbf35503
authored
Jul 18, 2019
by
chenjunxiong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
parent
3b25d4e5
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
298 additions
and
454 deletions
+298
-454
Development/文件下载接口修改(断点续传).html
+0
-419
Development/文件下载接口修改(断点续传).md
+10
-10
Plan/云存储第三阶段开发说明文档.md
+72
-25
Plan/云存储第三阶段模块说明文档.md
+216
-0
No files found.
Development/文件下载接口修改(断点续传).html
deleted
100644 → 0
View file @
3b25d4e5
<!doctype html>
<!doctype html>
<html>
<head>
<meta
charset=
'UTF-8'
><meta
name=
'viewport'
content=
'width=device-width initial-scale=1'
>
<title>
文件下载接口修改(断点续传)
</title><style
type=
'text/css'
>html
{
overflow-x
:
initial
!important
;}
:root
{
--bg-color
:
#ffffff
;
--text-color
:
#333333
;
--select-text-bg-color
:
#B5D6FC
;
--select-text-font-color
:
auto
;
--monospace
:
"Lucida Console"
,
Consolas
,
"Courier"
,
monospace
;
}
html
{
font-size
:
14px
;
background-color
:
var
(
--bg-color
);
color
:
var
(
--text-color
);
font-family
:
"Helvetica Neue"
,
Helvetica
,
Arial
,
sans-serif
;
-webkit-font-smoothing
:
antialiased
;
}
body
{
margin
:
0px
;
padding
:
0px
;
height
:
auto
;
bottom
:
0px
;
top
:
0px
;
left
:
0px
;
right
:
0px
;
font-size
:
1rem
;
line-height
:
1.42857
;
overflow-x
:
hidden
;
background
:
inherit
;
tab-size
:
4
;
}
iframe
{
margin
:
auto
;
}
a
.url
{
word-break
:
break-all
;
}
a
:active
,
a
:hover
{
outline
:
0px
;
}
.in-text-selection
,
::selection
{
text-shadow
:
none
;
background
:
var
(
--select-text-bg-color
);
color
:
var
(
--select-text-font-color
);
}
#write
{
margin
:
0px
auto
;
height
:
auto
;
width
:
inherit
;
word-break
:
normal
;
overflow-wrap
:
break-word
;
position
:
relative
;
white-space
:
normal
;
overflow-x
:
visible
;
padding-top
:
40px
;
}
#write
.first-line-indent
p
{
text-indent
:
2em
;
}
#write
.first-line-indent
li
p
,
#write
.first-line-indent
p
*
{
text-indent
:
0px
;
}
#write
.first-line-indent
li
{
margin-left
:
2em
;
}
.for-image
#write
{
padding-left
:
8px
;
padding-right
:
8px
;
}
body
.typora-export
{
padding-left
:
30px
;
padding-right
:
30px
;
}
.typora-export
.footnote-line
,
.typora-export
li
,
.typora-export
p
{
white-space
:
pre-wrap
;
}
@media
screen
and
(
max-width
:
500px
)
{
body
.typora-export
{
padding-left
:
0px
;
padding-right
:
0px
;
}
#write
{
padding-left
:
20px
;
padding-right
:
20px
;
}
.CodeMirror-sizer
{
margin-left
:
0px
!important
;
}
.CodeMirror-gutters
{
display
:
none
!important
;
}
}
#write
li
>
figure
:last-child
{
margin-bottom
:
0.5rem
;
}
#write
ol
,
#write
ul
{
position
:
relative
;
}
img
{
max-width
:
100%
;
vertical-align
:
middle
;
}
button
,
input
,
select
,
textarea
{
color
:
inherit
;
font
:
inherit
;
}
input
[
type
=
"checkbox"
],
input
[
type
=
"radio"
]
{
line-height
:
normal
;
padding
:
0px
;
}
*,
::after
,
::before
{
box-sizing
:
border-box
;
}
#write
h1
,
#write
h2
,
#write
h3
,
#write
h4
,
#write
h5
,
#write
h6
,
#write
p
,
#write
pre
{
width
:
inherit
;
}
#write
h1
,
#write
h2
,
#write
h3
,
#write
h4
,
#write
h5
,
#write
h6
,
#write
p
{
position
:
relative
;
}
p
{
line-height
:
inherit
;
}
h1
,
h2
,
h3
,
h4
,
h5
,
h6
{
break-after
:
avoid-page
;
break-inside
:
avoid
;
orphans
:
2
;
}
p
{
orphans
:
4
;
}
h1
{
font-size
:
2rem
;
}
h2
{
font-size
:
1.8rem
;
}
h3
{
font-size
:
1.6rem
;
}
h4
{
font-size
:
1.4rem
;
}
h5
{
font-size
:
1.2rem
;
}
h6
{
font-size
:
1rem
;
}
.md-math-block
,
.md-rawblock
,
h1
,
h2
,
h3
,
h4
,
h5
,
h6
,
p
{
margin-top
:
1rem
;
margin-bottom
:
1rem
;
}
.hidden
{
display
:
none
;
}
.md-blockmeta
{
color
:
rgb
(
204
,
204
,
204
);
font-weight
:
700
;
font-style
:
italic
;
}
a
{
cursor
:
pointer
;
}
sup
.md-footnote
{
padding
:
2px
4px
;
background-color
:
rgba
(
238
,
238
,
238
,
0.7
);
color
:
rgb
(
85
,
85
,
85
);
border-radius
:
4px
;
cursor
:
pointer
;
}
sup
.md-footnote
a
,
sup
.md-footnote
a
:hover
{
color
:
inherit
;
text-transform
:
inherit
;
text-decoration
:
inherit
;
}
#write
input
[
type
=
"checkbox"
]
{
cursor
:
pointer
;
width
:
inherit
;
height
:
inherit
;
}
figure
{
overflow-x
:
auto
;
margin
:
1.2em
0px
;
max-width
:
calc
(
100%
+
16px
);
padding
:
0px
;
}
figure
>
table
{
margin
:
0px
!important
;
}
tr
{
break-inside
:
avoid
;
break-after
:
auto
;
}
thead
{
display
:
table-header-group
;
}
table
{
border-collapse
:
collapse
;
border-spacing
:
0px
;
width
:
100%
;
overflow
:
auto
;
break-inside
:
auto
;
text-align
:
left
;
}
table
.md-table
td
{
min-width
:
32px
;
}
.CodeMirror-gutters
{
border-right
:
0px
;
background-color
:
inherit
;
}
.CodeMirror-linenumber
{
user-select
:
none
;
}
.CodeMirror
{
text-align
:
left
;
}
.CodeMirror-placeholder
{
opacity
:
0.3
;
}
.CodeMirror
pre
{
padding
:
0px
4px
;
}
.CodeMirror-lines
{
padding
:
0px
;
}
div
.hr
:focus
{
cursor
:
none
;
}
#write
pre
{
white-space
:
pre-wrap
;
}
#write
.fences-no-line-wrapping
pre
{
white-space
:
pre
;
}
#write
pre
.ty-contain-cm
{
white-space
:
normal
;
}
.CodeMirror-gutters
{
margin-right
:
4px
;
}
.md-fences
{
font-size
:
0.9rem
;
display
:
block
;
break-inside
:
avoid
;
text-align
:
left
;
overflow
:
visible
;
white-space
:
pre
;
background
:
inherit
;
position
:
relative
!important
;
}
.md-diagram-panel
{
width
:
100%
;
margin-top
:
10px
;
text-align
:
center
;
padding-top
:
0px
;
padding-bottom
:
8px
;
overflow-x
:
auto
;
}
#write
.md-fences.mock-cm
{
white-space
:
pre-wrap
;
}
.md-fences.md-fences-with-lineno
{
padding-left
:
0px
;
}
#write
.fences-no-line-wrapping
.md-fences.mock-cm
{
white-space
:
pre
;
overflow-x
:
auto
;
}
.md-fences.mock-cm.md-fences-with-lineno
{
padding-left
:
8px
;
}
.CodeMirror-line
,
twitterwidget
{
break-inside
:
avoid
;
}
.footnotes
{
opacity
:
0.8
;
font-size
:
0.9rem
;
margin-top
:
1em
;
margin-bottom
:
1em
;
}
.footnotes
+
.footnotes
{
margin-top
:
0px
;
}
.md-reset
{
margin
:
0px
;
padding
:
0px
;
border
:
0px
;
outline
:
0px
;
vertical-align
:
top
;
background
:
0px
0px
;
text-decoration
:
none
;
text-shadow
:
none
;
float
:
none
;
position
:
static
;
width
:
auto
;
height
:
auto
;
white-space
:
nowrap
;
cursor
:
inherit
;
-webkit-tap-highlight-color
:
transparent
;
line-height
:
normal
;
font-weight
:
400
;
text-align
:
left
;
box-sizing
:
content-box
;
direction
:
ltr
;
}
li
div
{
padding-top
:
0px
;
}
blockquote
{
margin
:
1rem
0px
;
}
li
.mathjax-block
,
li
p
{
margin
:
0.5rem
0px
;
}
li
{
margin
:
0px
;
position
:
relative
;
}
blockquote
>
:last-child
{
margin-bottom
:
0px
;
}
blockquote
>
:first-child
,
li
>
:first-child
{
margin-top
:
0px
;
}
.footnotes-area
{
color
:
rgb
(
136
,
136
,
136
);
margin-top
:
0.714rem
;
padding-bottom
:
0.143rem
;
white-space
:
normal
;
}
#write
.footnote-line
{
white-space
:
pre-wrap
;
}
@media
print
{
body
,
html
{
border
:
1px
solid
transparent
;
height
:
99%
;
break-after
:
avoid
;
break-before
:
avoid
;
}
#write
{
margin-top
:
0px
;
padding-top
:
0px
;
border-color
:
transparent
!important
;
}
.typora-export
*
{
-webkit-print-color-adjust
:
exact
;
}
html
.blink-to-pdf
{
font-size
:
13px
;
}
.typora-export
#write
{
padding-left
:
32px
;
padding-right
:
32px
;
padding-bottom
:
0px
;
break-after
:
avoid
;
}
.typora-export
#write
::after
{
height
:
0px
;
}
}
.footnote-line
{
margin-top
:
0.714em
;
font-size
:
0.7em
;
}
a
img
,
img
a
{
cursor
:
pointer
;
}
pre
.md-meta-block
{
font-size
:
0.8rem
;
min-height
:
0.8rem
;
white-space
:
pre-wrap
;
background
:
rgb
(
204
,
204
,
204
);
display
:
block
;
overflow-x
:
hidden
;
}
p
>
.md-image
:only-child:not
(
.md-img-error
)
img
,
p
>
img
:only-child
{
display
:
block
;
margin
:
auto
;
}
p
>
.md-image
:only-child
{
display
:
inline-block
;
width
:
100%
;
}
#write
.MathJax_Display
{
margin
:
0.8em
0px
0px
;
}
.md-math-block
{
width
:
100%
;
}
.md-math-block
:not
(
:empty
)
::after
{
display
:
none
;
}
[
contenteditable
=
"true"
]
:active
,
[
contenteditable
=
"true"
]
:focus
{
outline
:
0px
;
box-shadow
:
none
;
}
.md-task-list-item
{
position
:
relative
;
list-style-type
:
none
;
}
.task-list-item.md-task-list-item
{
padding-left
:
0px
;
}
.md-task-list-item
>
input
{
position
:
absolute
;
top
:
0px
;
left
:
0px
;
margin-left
:
-1.2em
;
margin-top
:
calc
(
1em
-
10px
);
border
:
none
;
}
.math
{
font-size
:
1rem
;
}
.md-toc
{
min-height
:
3.58rem
;
position
:
relative
;
font-size
:
0.9rem
;
border-radius
:
10px
;
}
.md-toc-content
{
position
:
relative
;
margin-left
:
0px
;
}
.md-toc-content
::after
,
.md-toc
::after
{
display
:
none
;
}
.md-toc-item
{
display
:
block
;
color
:
rgb
(
65
,
131
,
196
);
}
.md-toc-item
a
{
text-decoration
:
none
;
}
.md-toc-inner
:hover
{
text-decoration
:
underline
;
}
.md-toc-inner
{
display
:
inline-block
;
cursor
:
pointer
;
}
.md-toc-h1
.md-toc-inner
{
margin-left
:
0px
;
font-weight
:
700
;
}
.md-toc-h2
.md-toc-inner
{
margin-left
:
2em
;
}
.md-toc-h3
.md-toc-inner
{
margin-left
:
4em
;
}
.md-toc-h4
.md-toc-inner
{
margin-left
:
6em
;
}
.md-toc-h5
.md-toc-inner
{
margin-left
:
8em
;
}
.md-toc-h6
.md-toc-inner
{
margin-left
:
10em
;
}
@media
screen
and
(
max-width
:
48em
)
{
.md-toc-h3
.md-toc-inner
{
margin-left
:
3.5em
;
}
.md-toc-h4
.md-toc-inner
{
margin-left
:
5em
;
}
.md-toc-h5
.md-toc-inner
{
margin-left
:
6.5em
;
}
.md-toc-h6
.md-toc-inner
{
margin-left
:
8em
;
}
}
a
.md-toc-inner
{
font-size
:
inherit
;
font-style
:
inherit
;
font-weight
:
inherit
;
line-height
:
inherit
;
}
.footnote-line
a
:not
(
.reversefootnote
)
{
color
:
inherit
;
}
.md-attr
{
display
:
none
;
}
.md-fn-count
::after
{
content
:
"."
;
}
code
,
pre
,
samp
,
tt
{
font-family
:
var
(
--monospace
);
}
kbd
{
margin
:
0px
0.1em
;
padding
:
0.1em
0.6em
;
font-size
:
0.8em
;
color
:
rgb
(
36
,
39
,
41
);
background
:
rgb
(
255
,
255
,
255
);
border
:
1px
solid
rgb
(
173
,
179
,
185
);
border-radius
:
3px
;
box-shadow
:
rgba
(
12
,
13
,
14
,
0.2
)
0px
1px
0px
,
rgb
(
255
,
255
,
255
)
0px
0px
0px
2px
inset
;
white-space
:
nowrap
;
vertical-align
:
middle
;
}
.md-comment
{
color
:
rgb
(
162
,
127
,
3
);
opacity
:
0.8
;
font-family
:
var
(
--monospace
);
}
code
{
text-align
:
left
;
vertical-align
:
initial
;
}
a
.md-print-anchor
{
white-space
:
pre
!important
;
border-width
:
initial
!important
;
border-style
:
none
!important
;
border-color
:
initial
!important
;
display
:
inline-block
!important
;
position
:
absolute
!important
;
width
:
1px
!important
;
right
:
0px
!important
;
outline
:
0px
!important
;
background
:
0px
0px
!important
;
text-decoration
:
initial
!important
;
text-shadow
:
initial
!important
;
}
.md-inline-math
.MathJax_SVG
.noError
{
display
:
none
!important
;
}
.html-for-mac
.inline-math-svg
.MathJax_SVG
{
vertical-align
:
0.2px
;
}
.md-math-block
.MathJax_SVG_Display
{
text-align
:
center
;
margin
:
0px
;
position
:
relative
;
text-indent
:
0px
;
max-width
:
none
;
max-height
:
none
;
min-height
:
0px
;
min-width
:
100%
;
width
:
auto
;
overflow-y
:
hidden
;
display
:
block
!important
;
}
.MathJax_SVG_Display
,
.md-inline-math
.MathJax_SVG_Display
{
width
:
auto
;
margin
:
inherit
;
display
:
inline-block
!important
;
}
.MathJax_SVG
.MJX-monospace
{
font-family
:
var
(
--monospace
);
}
.MathJax_SVG
.MJX-sans-serif
{
font-family
:
sans-serif
;
}
.MathJax_SVG
{
display
:
inline
;
font-style
:
normal
;
font-weight
:
400
;
line-height
:
normal
;
zoom
:
90%
;
text-indent
:
0px
;
text-align
:
left
;
text-transform
:
none
;
letter-spacing
:
normal
;
word-spacing
:
normal
;
overflow-wrap
:
normal
;
white-space
:
nowrap
;
float
:
none
;
direction
:
ltr
;
max-width
:
none
;
max-height
:
none
;
min-width
:
0px
;
min-height
:
0px
;
border
:
0px
;
padding
:
0px
;
margin
:
0px
;
}
.MathJax_SVG
*
{
transition
:
none
0s
ease
0s
;
}
.MathJax_SVG_Display
svg
{
vertical-align
:
middle
!important
;
margin-bottom
:
0px
!important
;
margin-top
:
0px
!important
;
}
.os-windows.monocolor-emoji
.md-emoji
{
font-family
:
"Segoe UI Symbol"
,
sans-serif
;
}
.md-diagram-panel
>
svg
{
max-width
:
100%
;
}
[
lang
=
"mermaid"
]
svg
,
[
lang
=
"flow"
]
svg
{
max-width
:
100%
;
height
:
auto
;
}
[
lang
=
"mermaid"
]
.node
text
{
font-size
:
1rem
;
}
table
tr
th
{
border-bottom
:
0px
;
}
video
{
max-width
:
100%
;
display
:
block
;
margin
:
0px
auto
;
}
iframe
{
max-width
:
100%
;
width
:
100%
;
border
:
none
;
}
.highlight
td
,
.highlight
tr
{
border
:
0px
;
}
.CodeMirror
{
height
:
auto
;
}
.CodeMirror.cm-s-inner
{
background
:
inherit
;
}
.CodeMirror-scroll
{
overflow
:
auto
hidden
;
z-index
:
3
;
}
.CodeMirror-gutter-filler
,
.CodeMirror-scrollbar-filler
{
background-color
:
rgb
(
255
,
255
,
255
);
}
.CodeMirror-gutters
{
border-right
:
1px
solid
rgb
(
221
,
221
,
221
);
background
:
inherit
;
white-space
:
nowrap
;
}
.CodeMirror-linenumber
{
padding
:
0px
3px
0px
5px
;
text-align
:
right
;
color
:
rgb
(
153
,
153
,
153
);
}
.cm-s-inner
.cm-keyword
{
color
:
rgb
(
119
,
0
,
136
);
}
.cm-s-inner
.cm-atom
,
.cm-s-inner.cm-atom
{
color
:
rgb
(
34
,
17
,
153
);
}
.cm-s-inner
.cm-number
{
color
:
rgb
(
17
,
102
,
68
);
}
.cm-s-inner
.cm-def
{
color
:
rgb
(
0
,
0
,
255
);
}
.cm-s-inner
.cm-variable
{
color
:
rgb
(
0
,
0
,
0
);
}
.cm-s-inner
.cm-variable-2
{
color
:
rgb
(
0
,
85
,
170
);
}
.cm-s-inner
.cm-variable-3
{
color
:
rgb
(
0
,
136
,
85
);
}
.cm-s-inner
.cm-string
{
color
:
rgb
(
170
,
17
,
17
);
}
.cm-s-inner
.cm-property
{
color
:
rgb
(
0
,
0
,
0
);
}
.cm-s-inner
.cm-operator
{
color
:
rgb
(
152
,
26
,
26
);
}
.cm-s-inner
.cm-comment
,
.cm-s-inner.cm-comment
{
color
:
rgb
(
170
,
85
,
0
);
}
.cm-s-inner
.cm-string-2
{
color
:
rgb
(
255
,
85
,
0
);
}
.cm-s-inner
.cm-meta
{
color
:
rgb
(
85
,
85
,
85
);
}
.cm-s-inner
.cm-qualifier
{
color
:
rgb
(
85
,
85
,
85
);
}
.cm-s-inner
.cm-builtin
{
color
:
rgb
(
51
,
0
,
170
);
}
.cm-s-inner
.cm-bracket
{
color
:
rgb
(
153
,
153
,
119
);
}
.cm-s-inner
.cm-tag
{
color
:
rgb
(
17
,
119
,
0
);
}
.cm-s-inner
.cm-attribute
{
color
:
rgb
(
0
,
0
,
204
);
}
.cm-s-inner
.cm-header
,
.cm-s-inner.cm-header
{
color
:
rgb
(
0
,
0
,
255
);
}
.cm-s-inner
.cm-quote
,
.cm-s-inner.cm-quote
{
color
:
rgb
(
0
,
153
,
0
);
}
.cm-s-inner
.cm-hr
,
.cm-s-inner.cm-hr
{
color
:
rgb
(
153
,
153
,
153
);
}
.cm-s-inner
.cm-link
,
.cm-s-inner.cm-link
{
color
:
rgb
(
0
,
0
,
204
);
}
.cm-negative
{
color
:
rgb
(
221
,
68
,
68
);
}
.cm-positive
{
color
:
rgb
(
34
,
153
,
34
);
}
.cm-header
,
.cm-strong
{
font-weight
:
700
;
}
.cm-del
{
text-decoration
:
line-through
;
}
.cm-em
{
font-style
:
italic
;
}
.cm-link
{
text-decoration
:
underline
;
}
.cm-error
{
color
:
red
;
}
.cm-invalidchar
{
color
:
red
;
}
.cm-constant
{
color
:
rgb
(
38
,
139
,
210
);
}
.cm-defined
{
color
:
rgb
(
181
,
137
,
0
);
}
div
.CodeMirror
span
.CodeMirror-matchingbracket
{
color
:
rgb
(
0
,
255
,
0
);
}
div
.CodeMirror
span
.CodeMirror-nonmatchingbracket
{
color
:
rgb
(
255
,
34
,
34
);
}
.cm-s-inner
.CodeMirror-activeline-background
{
background
:
inherit
;
}
.CodeMirror
{
position
:
relative
;
overflow
:
hidden
;
}
.CodeMirror-scroll
{
height
:
100%
;
outline
:
0px
;
position
:
relative
;
box-sizing
:
content-box
;
background
:
inherit
;
}
.CodeMirror-sizer
{
position
:
relative
;
}
.CodeMirror-gutter-filler
,
.CodeMirror-hscrollbar
,
.CodeMirror-scrollbar-filler
,
.CodeMirror-vscrollbar
{
position
:
absolute
;
z-index
:
6
;
display
:
none
;
}
.CodeMirror-vscrollbar
{
right
:
0px
;
top
:
0px
;
overflow
:
hidden
;
}
.CodeMirror-hscrollbar
{
bottom
:
0px
;
left
:
0px
;
overflow
:
hidden
;
}
.CodeMirror-scrollbar-filler
{
right
:
0px
;
bottom
:
0px
;
}
.CodeMirror-gutter-filler
{
left
:
0px
;
bottom
:
0px
;
}
.CodeMirror-gutters
{
position
:
absolute
;
left
:
0px
;
top
:
0px
;
padding-bottom
:
30px
;
z-index
:
3
;
}
.CodeMirror-gutter
{
white-space
:
normal
;
height
:
100%
;
box-sizing
:
content-box
;
padding-bottom
:
30px
;
margin-bottom
:
-32px
;
display
:
inline-block
;
}
.CodeMirror-gutter-wrapper
{
position
:
absolute
;
z-index
:
4
;
background
:
0px
0px
!important
;
border
:
none
!important
;
}
.CodeMirror-gutter-background
{
position
:
absolute
;
top
:
0px
;
bottom
:
0px
;
z-index
:
4
;
}
.CodeMirror-gutter-elt
{
position
:
absolute
;
cursor
:
default
;
z-index
:
4
;
}
.CodeMirror-lines
{
cursor
:
text
;
}
.CodeMirror
pre
{
border-radius
:
0px
;
border-width
:
0px
;
background
:
0px
0px
;
font-family
:
inherit
;
font-size
:
inherit
;
margin
:
0px
;
white-space
:
pre
;
overflow-wrap
:
normal
;
color
:
inherit
;
z-index
:
2
;
position
:
relative
;
overflow
:
visible
;
}
.CodeMirror-wrap
pre
{
overflow-wrap
:
break-word
;
white-space
:
pre-wrap
;
word-break
:
normal
;
}
.CodeMirror-code
pre
{
border-right
:
30px
solid
transparent
;
width
:
fit-content
;
}
.CodeMirror-wrap
.CodeMirror-code
pre
{
border-right
:
none
;
width
:
auto
;
}
.CodeMirror-linebackground
{
position
:
absolute
;
left
:
0px
;
right
:
0px
;
top
:
0px
;
bottom
:
0px
;
z-index
:
0
;
}
.CodeMirror-linewidget
{
position
:
relative
;
z-index
:
2
;
overflow
:
auto
;
}
.CodeMirror-wrap
.CodeMirror-scroll
{
overflow-x
:
hidden
;
}
.CodeMirror-measure
{
position
:
absolute
;
width
:
100%
;
height
:
0px
;
overflow
:
hidden
;
visibility
:
hidden
;
}
.CodeMirror-measure
pre
{
position
:
static
;
}
.CodeMirror
div
.CodeMirror-cursor
{
position
:
absolute
;
visibility
:
hidden
;
border-right
:
none
;
width
:
0px
;
}
.CodeMirror
div
.CodeMirror-cursor
{
visibility
:
hidden
;
}
.CodeMirror-focused
div
.CodeMirror-cursor
{
visibility
:
inherit
;
}
.cm-searching
{
background
:
rgba
(
255
,
255
,
0
,
0.4
);
}
@media
print
{
.CodeMirror
div
.CodeMirror-cursor
{
visibility
:
hidden
;
}
}
.cm-s-inner
.cm-variable
,
.cm-s-inner
.cm-operator
,
.cm-s-inner
.cm-property
{
color
:
rgb
(
184
,
191
,
198
);
}
.cm-s-inner
.cm-keyword
{
color
:
rgb
(
200
,
143
,
208
);
}
.cm-s-inner
.cm-tag
{
color
:
rgb
(
125
,
244
,
106
);
}
.cm-s-inner
.cm-attribute
{
color
:
rgb
(
117
,
117
,
228
);
}
.CodeMirror
div
.CodeMirror-cursor
{
border-left
:
1px
solid
rgb
(
184
,
191
,
198
);
z-index
:
3
;
}
.cm-s-inner
.cm-string
{
color
:
rgb
(
210
,
107
,
107
);
}
.cm-s-inner
.cm-comment
,
.cm-s-inner.cm-comment
{
color
:
rgb
(
218
,
146
,
74
);
}
.cm-s-inner
.cm-header
,
.cm-s-inner
.cm-def
,
.cm-s-inner.cm-header
,
.cm-s-inner.cm-def
{
color
:
rgb
(
141
,
141
,
240
);
}
.cm-s-inner
.cm-quote
,
.cm-s-inner.cm-quote
{
color
:
rgb
(
87
,
172
,
87
);
}
.cm-s-inner
.cm-hr
{
color
:
rgb
(
216
,
213
,
213
);
}
.cm-s-inner
.cm-link
{
color
:
rgb
(
211
,
211
,
239
);
}
.cm-s-inner
.cm-negative
{
color
:
rgb
(
217
,
80
,
80
);
}
.cm-s-inner
.cm-positive
{
color
:
rgb
(
80
,
230
,
80
);
}
.cm-s-inner
.cm-string-2
{
color
:
rgb
(
255
,
85
,
0
);
}
.cm-s-inner
.cm-meta
,
.cm-s-inner
.cm-qualifier
{
color
:
rgb
(
183
,
179
,
179
);
}
.cm-s-inner
.cm-builtin
{
color
:
rgb
(
243
,
179
,
248
);
}
.cm-s-inner
.cm-bracket
{
color
:
rgb
(
153
,
153
,
119
);
}
.cm-s-inner
.cm-atom
,
.cm-s-inner.cm-atom
{
color
:
rgb
(
132
,
182
,
203
);
}
.cm-s-inner
.cm-number
{
color
:
rgb
(
100
,
171
,
143
);
}
.cm-s-inner
.cm-variable
{
color
:
rgb
(
184
,
191
,
198
);
}
.cm-s-inner
.cm-variable-2
{
color
:
rgb
(
159
,
186
,
213
);
}
.cm-s-inner
.cm-variable-3
{
color
:
rgb
(
28
,
198
,
133
);
}
.CodeMirror-selectedtext
,
.CodeMirror-selected
{
background
:
rgb
(
74
,
137
,
220
);
text-shadow
:
none
;
color
:
rgb
(
255
,
255
,
255
)
!important
;
}
.CodeMirror-gutters
{
border-right
:
none
;
}
:root
{
--bg-color
:
#363B40
;
--side-bar-bg-color
:
#2E3033
;
--text-color
:
#b8bfc6
;
--select-text-bg-color
:
#4a89dc
;
--control-text-color
:
#b7b7b7
;
--control-text-hover-color
:
#eee
;
--window-border
:
1px
solid
#555
;
--active-file-bg-color
:
rgb
(
34
,
34
,
34
);
--active-file-border-color
:
#8d8df0
;
--active-file-text-color
:
white
;
--item-hover-bg-color
:
#70717d
;
--item-hover-text-color
:
white
;
--primary-color
:
#6dc1e7
;
--rawblock-edit-panel-bd
:
#333
;
}
html
{
font-size
:
16px
;
}
html
,
body
{
text-size-adjust
:
100%
;
background
:
var
(
--bg-color
);
fill
:
currentcolor
;
line-height
:
1.625rem
;
}
#write
{
max-width
:
914px
;
}
html
,
body
,
button
,
input
,
select
,
textarea
,
div
.code-tooltip-content
{
color
:
rgb
(
184
,
191
,
198
);
border-color
:
transparent
;
}
div
.code-tooltip
,
.md-hover-tip
.md-arrow
::after
{
background
:
rgb
(
51
,
51
,
51
);
}
.popover.bottom
>
.arrow
::after
{
border-bottom-color
:
rgb
(
51
,
51
,
51
);
}
html
,
body
,
button
,
input
,
select
,
textarea
{
font-family
:
"Helvetica Neue"
,
Helvetica
,
Arial
,
sans-serif
;
}
hr
{
height
:
2px
;
border
:
0px
;
margin
:
24px
0px
!important
;
}
h1
,
h2
,
h3
,
h4
,
h5
,
h6
{
font-family
:
"Lucida Grande"
,
Corbel
,
sans-serif
;
font-weight
:
normal
;
clear
:
both
;
overflow-wrap
:
break-word
;
margin
:
0px
;
padding
:
0px
;
color
:
rgb
(
222
,
222
,
222
);
}
h1
{
font-size
:
2.5rem
;
line-height
:
2.75rem
;
margin-bottom
:
1.5rem
;
letter-spacing
:
-1.5px
;
}
h2
{
font-size
:
1.63rem
;
line-height
:
1.875rem
;
margin-bottom
:
1.5rem
;
letter-spacing
:
-1px
;
font-weight
:
bold
;
}
h3
{
font-size
:
1.17rem
;
line-height
:
1.5rem
;
margin-bottom
:
1.5rem
;
letter-spacing
:
-1px
;
font-weight
:
bold
;
}
h4
{
font-size
:
1.12rem
;
line-height
:
1.375rem
;
margin-bottom
:
1.5rem
;
color
:
white
;
}
h5
{
font-size
:
0.97rem
;
line-height
:
1.25rem
;
margin-bottom
:
1.5rem
;
font-weight
:
bold
;
}
h6
{
font-size
:
0.93rem
;
line-height
:
1rem
;
margin-bottom
:
0.75rem
;
color
:
white
;
}
@media
(
min-width
:
980px
)
{
h3
.md-focus
::before
,
h4
.md-focus
::before
,
h5
.md-focus
::before
,
h6
.md-focus
::before
{
color
:
rgb
(
221
,
221
,
221
);
border
:
1px
solid
rgb
(
221
,
221
,
221
);
border-radius
:
3px
;
position
:
absolute
;
left
:
-1.64286rem
;
top
:
0.357143rem
;
float
:
left
;
font-size
:
9px
;
padding-left
:
2px
;
padding-right
:
2px
;
vertical-align
:
bottom
;
font-weight
:
normal
;
line-height
:
normal
;
}
h3
.md-focus
::before
{
content
:
"h3"
;
}
h4
.md-focus
::before
{
content
:
"h4"
;
}
h5
.md-focus
::before
{
content
:
"h5"
;
top
:
0px
;
}
h6
.md-focus
::before
{
content
:
"h6"
;
top
:
0px
;
}
}
a
{
text-decoration
:
none
;
outline
:
0px
;
}
a
:hover
{
outline
:
0px
;
}
a
:focus
{
outline
:
dotted
thin
;
}
sup
.md-footnote
{
background-color
:
rgb
(
85
,
85
,
85
);
color
:
rgb
(
221
,
221
,
221
);
}
p
{
overflow-wrap
:
break-word
;
}
p
,
ul
,
dd
,
ol
,
hr
,
address
,
pre
,
table
,
iframe
,
.wp-caption
,
.wp-audio-shortcode
,
.wp-video-shortcode
{
margin-top
:
0px
;
margin-bottom
:
1.5rem
;
}
li
>
blockquote
{
margin-bottom
:
0px
;
}
audio
:not
([
controls
])
{
display
:
none
;
}
[
hidden
]
{
display
:
none
;
}
.in-text-selection
,
::selection
{
background
:
rgb
(
74
,
137
,
220
);
color
:
rgb
(
255
,
255
,
255
);
text-shadow
:
none
;
}
ul
,
ol
{
padding
:
0px
0px
0px
1.875rem
;
}
ul
{
list-style
:
square
;
}
ol
{
list-style
:
decimal
;
}
ul
ul
,
ol
ol
,
ul
ol
,
ol
ul
{
margin
:
0px
;
}
b
,
th
,
dt
,
strong
{
font-weight
:
bold
;
}
i
,
em
,
dfn
,
cite
{
font-style
:
italic
;
}
blockquote
{
margin
:
35px
0px
1.875rem
1.875rem
;
border-left
:
2px
solid
rgb
(
71
,
77
,
84
);
padding-left
:
30px
;
}
pre
,
code
,
kbd
,
tt
,
var
{
background
:
rgba
(
0
,
0
,
0
,
0.05
);
font-size
:
0.875rem
;
font-family
:
Monaco
,
Consolas
,
"Andale Mono"
,
"DejaVu Sans Mono"
,
monospace
;
}
kbd
{
padding
:
2px
4px
;
font-size
:
90%
;
color
:
rgb
(
255
,
255
,
255
);
background-color
:
rgb
(
51
,
51
,
51
);
border-radius
:
3px
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.25
)
0px
-1px
0px
inset
;
}
pre
.md-fences
{
padding
:
10px
10px
10px
30px
;
margin-bottom
:
20px
;
background
:
rgb
(
51
,
51
,
51
);
}
.CodeMirror-gutters
{
background
:
rgb
(
51
,
51
,
51
);
border-right
:
1px
solid
transparent
;
}
.enable-diagrams
pre
.md-fences
[
lang
=
"sequence"
]
.code-tooltip
,
.enable-diagrams
pre
.md-fences
[
lang
=
"flow"
]
.code-tooltip
,
.enable-diagrams
pre
.md-fences
[
lang
=
"mermaid"
]
.code-tooltip
{
bottom
:
-2.2em
;
right
:
4px
;
}
code
,
kbd
,
tt
,
var
{
padding
:
2px
5px
;
}
table
{
max-width
:
100%
;
width
:
100%
;
border-collapse
:
collapse
;
border-spacing
:
0px
;
}
th
,
td
{
padding
:
5px
10px
;
vertical-align
:
top
;
}
a
{
transition
:
all
0.2s
ease-in-out
0s
;
}
hr
{
background
:
rgb
(
71
,
77
,
84
);
}
h1
{
margin-top
:
2em
;
}
a
{
color
:
rgb
(
224
,
224
,
224
);
text-decoration
:
underline
;
}
a
:hover
{
color
:
rgb
(
255
,
255
,
255
);
}
.md-inline-math
script
{
color
:
rgb
(
129
,
177
,
219
);
}
b
,
th
,
dt
,
strong
{
color
:
rgb
(
222
,
222
,
222
);
}
mark
{
background
:
rgb
(
211
,
212
,
14
);
}
blockquote
{
color
:
rgb
(
157
,
162
,
166
);
}
table
a
{
color
:
rgb
(
222
,
222
,
222
);
}
th
,
td
{
border
:
1px
solid
rgb
(
71
,
77
,
84
);
}
.task-list
{
padding-left
:
0px
;
}
.md-task-list-item
{
padding-left
:
1.25rem
;
}
.md-task-list-item
>
input
{
top
:
auto
;
}
.md-task-list-item
>
input
::before
{
content
:
""
;
display
:
inline-block
;
width
:
0.875rem
;
height
:
0.875rem
;
vertical-align
:
middle
;
text-align
:
center
;
border
:
1px
solid
rgb
(
184
,
191
,
198
);
background-color
:
rgb
(
54
,
59
,
64
);
margin-top
:
-0.4rem
;
}
.md-task-list-item
>
input
:checked::before
,
.md-task-list-item
>
input
[
checked
]
::before
{
content
:
"√"
;
font-size
:
0.625rem
;
line-height
:
0.625rem
;
color
:
rgb
(
222
,
222
,
222
);
}
.auto-suggest-container
{
border
:
0px
;
background-color
:
rgb
(
82
,
92
,
101
);
}
#typora-quick-open
{
background-color
:
rgb
(
82
,
92
,
101
);
}
#typora-quick-open
input
{
background-color
:
rgb
(
82
,
92
,
101
);
border-width
:
0px
0px
1px
;
border-top-style
:
initial
;
border-right-style
:
initial
;
border-left-style
:
initial
;
border-top-color
:
initial
;
border-right-color
:
initial
;
border-left-color
:
initial
;
border-image
:
initial
;
border-bottom-style
:
solid
;
border-bottom-color
:
grey
;
}
.typora-quick-open-item
{
background-color
:
inherit
;
color
:
inherit
;
}
.typora-quick-open-item.active
,
.typora-quick-open-item
:hover
{
background-color
:
rgb
(
77
,
139
,
219
);
color
:
white
;
}
.typora-quick-open-item
:hover
{
background-color
:
rgba
(
77
,
139
,
219
,
0.8
);
}
.typora-search-spinner
>
div
{
background-color
:
rgb
(
255
,
255
,
255
);
}
#write
pre
.md-meta-block
{
border-bottom
:
1px
dashed
rgb
(
204
,
204
,
204
);
background
:
transparent
;
padding-bottom
:
0.6em
;
line-height
:
1.6em
;
}
.btn
,
.btn
.btn-default
{
background
:
transparent
;
color
:
rgb
(
184
,
191
,
198
);
}
.ty-table-edit
{
border-top
:
1px
solid
gray
;
background-color
:
rgb
(
54
,
59
,
64
);
}
.popover-title
{
background
:
transparent
;
}
.md-image
>
.md-meta
{
color
:
rgb
(
187
,
187
,
187
);
background
:
transparent
;
}
.md-expand.md-image
>
.md-meta
{
color
:
rgb
(
221
,
221
,
221
);
}
#write
>
h3
::before
,
#write
>
h4
::before
,
#write
>
h5
::before
,
#write
>
h6
::before
{
border
:
none
;
border-radius
:
0px
;
color
:
rgb
(
136
,
136
,
136
);
text-decoration
:
underline
;
left
:
-1.4rem
;
top
:
0.2rem
;
}
#write
>
h3
.md-focus
::before
{
top
:
2px
;
}
#write
>
h4
.md-focus
::before
{
top
:
2px
;
}
.md-toc-item
{
color
:
rgb
(
168
,
194
,
220
);
}
#write
div
.md-toc-tooltip
{
background-color
:
rgb
(
54
,
59
,
64
);
}
.dropdown-menu
.btn
:hover
,
.dropdown-menu
.btn
:focus
,
.md-toc
.btn
:hover
,
.md-toc
.btn
:focus
{
color
:
white
;
background
:
black
;
}
#toc-dropmenu
{
background
:
rgba
(
50
,
54
,
59
,
0.93
);
border
:
1px
solid
rgba
(
253
,
253
,
253
,
0.15
);
}
#toc-dropmenu
.divider
{
background-color
:
rgb
(
155
,
155
,
155
);
}
.outline-expander
::before
{
top
:
2px
;
}
#typora-sidebar
{
box-shadow
:
none
;
border-right
:
none
;
}
.sidebar-tabs
{
border-bottom
:
0px
;
}
#typora-sidebar
:hover
.outline-title-wrapper
{
border-left
:
1px
dashed
;
}
.outline-title-wrapper
.btn
{
color
:
inherit
;
}
.outline-item
:hover
{
border-color
:
rgb
(
54
,
59
,
64
);
background-color
:
rgb
(
54
,
59
,
64
);
color
:
white
;
}
h1
.md-focus
.md-attr
,
h2
.md-focus
.md-attr
,
h3
.md-focus
.md-attr
,
h4
.md-focus
.md-attr
,
h5
.md-focus
.md-attr
,
h6
.md-focus
.md-attr
,
.md-header-span
.md-attr
{
color
:
rgb
(
140
,
142
,
146
);
display
:
inline
;
}
.md-comment
{
color
:
rgb
(
90
,
149
,
227
);
opacity
:
1
;
}
.md-inline-math
g
,
.md-inline-math
svg
{
stroke
:
rgb
(
184
,
191
,
198
)
!important
;
fill
:
rgb
(
184
,
191
,
198
)
!important
;
}
[
md-inline
=
"inline_math"
]
{
color
:
rgb
(
156
,
178
,
233
);
}
#math-inline-preview
.md-arrow
::after
{
background
:
black
;
}
.modal-content
{
background
:
var
(
--bg-color
);
border
:
0px
;
}
.modal-title
{
font-size
:
1.5em
;
}
.modal-content
input
{
background-color
:
rgba
(
26
,
21
,
21
,
0.51
);
color
:
white
;
}
.modal-content
.input-group-addon
{
background-color
:
rgba
(
0
,
0
,
0
,
0.17
);
color
:
white
;
}
.modal-backdrop
{
background-color
:
rgba
(
174
,
174
,
174
,
0.7
);
}
.modal-content
.btn-primary
{
border-color
:
var
(
--primary-color
);
}
.md-table-resize-popover
{
background-color
:
rgb
(
51
,
51
,
51
);
}
.form-inline
.input-group
.input-group-addon
{
color
:
white
;
}
#md-searchpanel
{
border-bottom
:
1px
dashed
grey
;
}
.context-menu
,
#spell-check-panel
,
#footer-word-count-info
{
background-color
:
rgb
(
66
,
70
,
74
);
}
.context-menu.dropdown-menu
.divider
,
.dropdown-menu
.divider
{
background-color
:
rgb
(
119
,
119
,
119
);
}
footer
{
color
:
inherit
;
}
@media
(
max-width
:
1000px
)
{
footer
{
border-top
:
none
;
}
footer
:hover
{
color
:
inherit
;
}
}
#file-info-file-path
.file-info-field-value
:hover
{
background-color
:
rgb
(
85
,
85
,
85
);
color
:
rgb
(
222
,
222
,
222
);
}
.megamenu-content
,
.megamenu-opened
header
{
background
:
var
(
--bg-color
);
}
.megamenu-menu-panel
h2
,
.megamenu-menu-panel
h1
,
.long-btn
{
color
:
inherit
;
}
.megamenu-menu-panel
input
[
type
=
"text"
]
{
background
:
inherit
;
border-width
:
0px
0px
1px
;
border-top-style
:
initial
;
border-right-style
:
initial
;
border-left-style
:
initial
;
border-color
:
initial
;
border-image
:
initial
;
border-bottom-style
:
solid
;
}
#recent-file-panel-action-btn
{
background
:
inherit
;
border
:
1px
solid
grey
;
}
.megamenu-menu-panel
.dropdown-menu
>
li
>
a
{
color
:
inherit
;
background-color
:
rgb
(
47
,
53
,
58
);
text-decoration
:
none
;
}
.megamenu-menu-panel
table
td
:nth-child
(
1
)
{
color
:
inherit
;
font-weight
:
bold
;
}
.megamenu-menu-panel
tbody
tr
:hover
td
:nth-child
(
1
)
{
color
:
white
;
}
.modal-footer
.btn-default
,
.modal-footer
.btn-primary
,
.modal-footer
.btn-default
:not
(
:hover
)
{
border
:
1px
solid
transparent
;
}
.btn-default
:hover
,
.btn-default
:focus
,
.btn-default.focus
,
.btn-default
:active
,
.btn-default.active
,
.open
>
.dropdown-toggle.btn-default
{
color
:
white
;
border
:
1px
solid
rgb
(
221
,
221
,
221
);
background-color
:
inherit
;
}
.modal-header
{
border-bottom
:
0px
;
}
.modal-footer
{
border-top
:
0px
;
}
#recent-file-panel
tbody
tr
:nth-child
(
2n-1
)
{
background-color
:
transparent
!important
;
}
.megamenu-menu-panel
tbody
tr
:hover
td
:nth-child
(
2
)
{
color
:
inherit
;
}
.megamenu-menu-panel
.btn
{
border
:
1px
solid
rgb
(
238
,
238
,
238
);
background
:
transparent
;
}
.mouse-hover
.toolbar-icon.btn
:hover
,
#w-full
.mouse-hover
,
#w-pin
.mouse-hover
{
background-color
:
inherit
;
}
.typora-node
::-webkit-scrollbar
{
width
:
5px
;
}
.typora-node
::-webkit-scrollbar-thumb:vertical
{
background
:
rgba
(
250
,
250
,
250
,
0.3
);
}
.typora-node
::-webkit-scrollbar-thumb:vertical:active
{
background
:
rgba
(
250
,
250
,
250
,
0.5
);
}
#w-unpin
{
background-color
:
rgb
(
65
,
130
,
196
);
}
#top-titlebar
,
#top-titlebar
*
{
color
:
var
(
--item-hover-text-color
);
}
.typora-sourceview-on
#toggle-sourceview-btn
,
#footer-word-count
:hover
,
.ty-show-word-count
#footer-word-count
{
background
:
rgb
(
51
,
51
,
51
);
}
#toggle-sourceview-btn
:hover
{
color
:
rgb
(
238
,
238
,
238
);
background
:
rgb
(
51
,
51
,
51
);
}
.on-focus-mode
.md-end-block
:not
(
.md-focus
)
:not
(
.md-focus-container
)
*
{
color
:
rgb
(
104
,
104
,
104
)
!important
;
}
.on-focus-mode
.md-end-block
:not
(
.md-focus
)
img
,
.on-focus-mode
.md-task-list-item
:not
(
.md-focus-container
)
>
input
{
}
.on-focus-mode
li
[
cid
]
:not
(
.md-focus-container
)
{
color
:
rgb
(
104
,
104
,
104
);
}
.on-focus-mode
.md-fences.md-focus
.CodeMirror-code
>
:not
(
.CodeMirror-activeline
)
*,
.on-focus-mode
.CodeMirror.cm-s-inner
:not
(
.CodeMirror-focused
)
*
{
color
:
rgb
(
104
,
104
,
104
)
!important
;
}
.on-focus-mode
.md-focus
,
.on-focus-mode
.md-focus-container
{
color
:
rgb
(
255
,
255
,
255
);
}
.on-focus-mode
#typora-source
.CodeMirror-code
>
:not
(
.CodeMirror-activeline
)
*
{
color
:
rgb
(
104
,
104
,
104
)
!important
;
}
#write
.md-focus
.md-diagram-panel
{
border
:
1px
solid
rgb
(
221
,
221
,
221
);
margin-left
:
-1px
;
width
:
calc
(
100%
+
2px
);
}
#write
.md-focus.md-fences-with-lineno
.md-diagram-panel
{
margin-left
:
auto
;
}
.md-diagram-panel-error
{
color
:
rgb
(
241
,
144
,
142
);
}
.active-tab-files
#info-panel-tab-file
,
.active-tab-files
#info-panel-tab-file
:hover
,
.active-tab-outline
#info-panel-tab-outline
,
.active-tab-outline
#info-panel-tab-outline
:hover
{
color
:
rgb
(
238
,
238
,
238
);
}
.sidebar-footer-item
:hover
,
.footer-item
:hover
{
background
:
inherit
;
color
:
white
;
}
.ty-side-sort-btn.active
,
.ty-side-sort-btn
:hover
,
.selected-folder-menu-item
a
::after
{
color
:
white
;
}
#sidebar-files-menu
{
border
:
1px
solid
;
box-shadow
:
rgba
(
0
,
0
,
0
,
0.79
)
4px
4px
20px
;
background-color
:
var
(
--bg-color
);
}
.file-list-item
{
border-bottom
:
none
;
}
.file-list-item-summary
{
opacity
:
1
;
}
.file-list-item.active
:first-child
{
border-top
:
none
;
}
.file-node-background
{
height
:
32px
;
}
.file-library-node.active
>
.file-node-content
,
.file-list-item.active
{
color
:
var
(
--active-file-text-color
);
}
.file-library-node.active
>
.file-node-background
{
background-color
:
var
(
--active-file-bg-color
);
}
.file-list-item.active
{
background-color
:
var
(
--active-file-bg-color
);
}
#ty-tooltip
{
background-color
:
black
;
color
:
rgb
(
238
,
238
,
238
);
}
.md-task-list-item
>
input
{
margin-left
:
-1.3em
;
margin-top
:
0.3rem
;
-webkit-appearance
:
none
;
}
.md-mathjax-midline
{
background-color
:
rgb
(
87
,
97
,
107
);
border-bottom
:
none
;
}
footer
.ty-footer
{
border-color
:
rgb
(
101
,
101
,
101
);
}
.typora-export
li
,
.typora-export
p
,
.typora-export
,
.footnote-line
{
white-space
:
normal
;}
</style>
</head>
<body
class=
'typora-export os-windows'
>
<div
id=
'write'
class =
'is-node'
><h1><a
name=
"%E4%BA%91%E5%AD%98%E5%82%A8%E7%B3%BB%E7%BB%9F%E5%AE%89%E5%85%A8%E5%8D%87%E7%BA%A7%EF%BC%9A"
class=
"md-header-anchor"
></a><span>
云存储系统安全升级:
</span></h1><div
class=
'md-toc'
mdtype=
'toc'
><p
class=
"md-toc-content"
><span
class=
"md-toc-item md-toc-h1"
data-ref=
"n0"
><a
class=
"md-toc-inner"
href=
"#%E4%BA%91%E5%AD%98%E5%82%A8%E7%B3%BB%E7%BB%9F%E5%AE%89%E5%85%A8%E5%8D%87%E7%BA%A7%EF%BC%9A"
>
云存储系统安全升级:
</a></span><span
class=
"md-toc-item md-toc-h2"
data-ref=
"n2"
><a
class=
"md-toc-inner"
href=
"#%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%E6%8E%A5%E5%8F%A3%E4%BF%AE%E6%94%B9%EF%BC%9A"
>
文件下载接口修改:
</a></span><span
class=
"md-toc-item md-toc-h3"
data-ref=
"n3"
><a
class=
"md-toc-inner"
href=
"#%E4%BF%AE%E6%94%B9%E8%AF%B4%E6%98%8E%EF%BC%9A"
>
修改说明:
</a></span><span
class=
"md-toc-item md-toc-h3"
data-ref=
"n24"
><a
class=
"md-toc-inner"
href=
"#http1.1%E5%8D%8F%E8%AE%AE%EF%BC%8C%E6%96%AD%E7%82%B9%E7%BB%AD%E4%BC%A0%EF%BC%88%E8%8C%83%E5%9B%B4%E8%AF%B7%E6%B1%82%EF%BC%89%E6%8A%80%E6%9C%AF%E8%AF%B4%E6%98%8E%EF%BC%9A"
>
HTTP1.1协议,断点续传(范围请求)技术说明:
</a></span><span
class=
"md-toc-item md-toc-h4"
data-ref=
"n69"
><a
class=
"md-toc-inner"
href=
"#%E4%B8%9A%E5%8A%A1%E9%80%BB%E8%BE%91%E8%AF%B4%E6%98%8E%EF%BC%9A"
>
业务逻辑说明:
</a></span><span
class=
"md-toc-item md-toc-h4"
data-ref=
"n94"
><a
class=
"md-toc-inner"
href=
"#%E6%B5%81%E7%A8%8B%E5%9B%BE%EF%BC%9A"
>
流程图:
</a></span></p></div><h2><a
name=
"%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%E6%8E%A5%E5%8F%A3%E4%BF%AE%E6%94%B9%EF%BC%9A"
class=
"md-header-anchor"
></a><span>
文件下载接口修改:
</span></h2><h3><a
name=
"%E4%BF%AE%E6%94%B9%E8%AF%B4%E6%98%8E%EF%BC%9A"
class=
"md-header-anchor"
></a><span>
修改说明:
</span></h3><ul><li><p><span>
文件下载由原来重定向改为HTTP请求Responses.Body返回文件byte内容
</span></p><ul><li><p><span>
这里解释下为什么我会选择重定向来做文件的获取:
</span></p><ul><li><p><span>
假如我们通过
</span><code>
FastFileStorageClient
</code><span>
的接口来获取
</span><strong><span>
100MB
</span></strong><span>
的文件,文件会以比特流的方式储存在服务器内存中,考虑到带宽问题,这个文件在
</span><code>
HTTP
</code><span>
请求正常请求且客户端没读取超时的情况下会一直占用
</span><strong><span>
100MB
</span></strong><span>
内存,这也只是一个下载请求。若加上断点续传,这
</span><strong><span>
100MB
</span></strong><span>
的文件可能会被多次加载在内存里,以
</span><strong><span>
BitComet
</span></strong><span>
为例:
</span></p><ul><li><strong><span>
BitComet
</span></strong><span>
在下载链接支持断点续传的情况下会默认创建
</span><strong><span>
5
</span></strong><span>
个
</span><code>
HTTP
</code><span>
请求来获取该文件,分别是
</span><strong><span>
0-20MB、20-40MB、40-60MB、60-80MB、80-100MB
</span></strong><span>
。
</span></li><li><span>
这时服务器会对应收到
</span><strong><span>
请求头
</span></strong><code>
Range
</code><span>
分别为这些范围的
</span><code>
HTTP
</code><span>
请求,并且在不同的线程内通过
</span><code>
FastFileStorageClient
</code><span>
的接口来获取这
</span><strong><span>
100MB
</span></strong><span>
大小的文件,并加载到内存中,最后通过
</span><strong><span>
请求头
</span></strong><code>
Range
</code><span>
参数来返回指定范围的比特流信息。
</span></li><li><span>
一个
</span><strong><span>
100MB
</span></strong><span>
的文件下载就让服务器消耗了
</span><strong><span>
500MB
</span></strong><span>
的内存,而且这也只是一个用户使用的情况下。
</span></li></ul></li><li><p><span>
这时我发现现有的下载代码逻辑在生产上是完全无法使用的,根本承受不住轻微的并发,并且对服务器内存要求是极高的,迫切需要一种以
</span><strong><span>
缓冲流方式
</span></strong><span>
加载文件的方法来获取返回文件,恰巧
</span><code>
FastDFS
</code><span>
的
</span><code>
fastdfs-nginx-module
</code><span>
支持,我就直接通过重定向的方法让
</span><code>
fastdfs-nginx-module
</code><span>
返回文件比特流,解决了文件下载的内存问题,并且减少了将完整文件加载至内存的过程减少了文件下载的等待时间。
</span></p></li></ul></li></ul></li><li><p><span>
原重定向的方法因FastDFS服务器支持断点续传,现断点续传需要通过代码实现
</span></p></li></ul><h3><a
name=
"http1.1%E5%8D%8F%E8%AE%AE%EF%BC%8C%E6%96%AD%E7%82%B9%E7%BB%AD%E4%BC%A0%EF%BC%88%E8%8C%83%E5%9B%B4%E8%AF%B7%E6%B1%82%EF%BC%89%E6%8A%80%E6%9C%AF%E8%AF%B4%E6%98%8E%EF%BC%9A"
class=
"md-header-anchor"
></a><span>
HTTP1.1协议,断点续传(范围请求)技术说明:
</span></h3><ul><li><p><span>
以Chrome浏览器获取视频为例(只要遵循
</span><code>
HTTP1.1
</code><span>
协议即可):
</span></p><ul><li><p><span>
浏览器首先发送一个简单GET请求,服务端返回200状态:
</span></p><p><span>
General:
</span></p><pre
spellcheck=
"false"
class=
"md-fences md-end-block md-fences-with-lineno ty-contain-cm modeLoaded"
lang=
"html"
><div
class=
"CodeMirror cm-s-inner CodeMirror-wrap"
lang=
"html"
><div
style=
"overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 31px;"
><textarea
autocorrect=
"off"
autocapitalize=
"off"
spellcheck=
"false"
tabindex=
"0"
style=
"position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"
></textarea></div><div
class=
"CodeMirror-scrollbar-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-gutter-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-scroll"
tabindex=
"-1"
><div
class=
"CodeMirror-sizer"
style=
"margin-left: 27px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"
><div
style=
"position: relative; top: 0px;"
><div
class=
"CodeMirror-lines"
role=
"presentation"
><div
role=
"presentation"
style=
"position: relative; outline: none;"
><div
class=
"CodeMirror-measure"
><pre><span>
xxxxxxxxxx
</span></pre><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
><div>
5
</div></div></div><div
class=
"CodeMirror-measure"
></div><div
style=
"position: relative; z-index: 1;"
></div><div
class=
"CodeMirror-code"
role=
"presentation"
style=
""
><div
class=
"CodeMirror-activeline"
style=
"position: relative;"
><div
class=
"CodeMirror-activeline-background CodeMirror-linebackground"
></div><div
class=
"CodeMirror-gutter-background CodeMirror-activeline-gutter"
style=
"left: -27px; width: 27px;"
></div><div
class=
"CodeMirror-gutter-wrapper CodeMirror-activeline-gutter"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
1
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Request URL: http://localhost:20003/rangeTest
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
2
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Request Method: GET
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
3
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Status Code: 200
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
4
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Remote Address: [::1]:20003
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
5
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Referrer Policy: no-referrer-when-downgrade
</span></pre></div></div></div></div></div></div><div
style=
"position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 130px;"
></div><div
class=
"CodeMirror-gutters"
style=
"height: 130px;"
><div
class=
"CodeMirror-gutter CodeMirror-linenumbers"
style=
"width: 26px;"
></div></div></div></div></pre><p><span>
Requset Headers:
</span></p><pre
spellcheck=
"false"
class=
"md-fences md-end-block md-fences-with-lineno ty-contain-cm modeLoaded"
lang=
"html"
><div
class=
"CodeMirror cm-s-inner CodeMirror-wrap"
lang=
"html"
><div
style=
"overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 31px;"
><textarea
autocorrect=
"off"
autocapitalize=
"off"
spellcheck=
"false"
tabindex=
"0"
style=
"position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"
></textarea></div><div
class=
"CodeMirror-scrollbar-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-gutter-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-scroll"
tabindex=
"-1"
><div
class=
"CodeMirror-sizer"
style=
"margin-left: 27px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"
><div
style=
"position: relative; top: 0px;"
><div
class=
"CodeMirror-lines"
role=
"presentation"
><div
role=
"presentation"
style=
"position: relative; outline: none;"
><div
class=
"CodeMirror-measure"
><pre><span>
xxxxxxxxxx
</span></pre><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
><div>
8
</div></div></div><div
class=
"CodeMirror-measure"
></div><div
style=
"position: relative; z-index: 1;"
></div><div
class=
"CodeMirror-code"
role=
"presentation"
style=
""
><div
class=
"CodeMirror-activeline"
style=
"position: relative;"
><div
class=
"CodeMirror-activeline-background CodeMirror-linebackground"
></div><div
class=
"CodeMirror-gutter-background CodeMirror-activeline-gutter"
style=
"left: -27px; width: 27px;"
></div><div
class=
"CodeMirror-gutter-wrapper CodeMirror-activeline-gutter"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
1
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
2
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Accept-Encoding: gzip, deflate, br
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
3
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Accept-Language: zh-CN,zh;q=0.9
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
4
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Connection: keep-alive
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
5
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
DNT: 1
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
6
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Host: localhost:20003
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
7
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Upgrade-Insecure-Requests: 1
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
8
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
</span></pre></div></div></div></div></div></div><div
style=
"position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 286px;"
></div><div
class=
"CodeMirror-gutters"
style=
"height: 286px;"
><div
class=
"CodeMirror-gutter CodeMirror-linenumbers"
style=
"width: 26px;"
></div></div></div></div></pre><p><span>
Response Headers:
</span></p><pre
spellcheck=
"false"
class=
"md-fences md-end-block md-fences-with-lineno ty-contain-cm modeLoaded"
lang=
"html"
><div
class=
"CodeMirror cm-s-inner CodeMirror-wrap"
lang=
"html"
><div
style=
"overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 31px;"
><textarea
autocorrect=
"off"
autocapitalize=
"off"
spellcheck=
"false"
tabindex=
"0"
style=
"position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"
></textarea></div><div
class=
"CodeMirror-scrollbar-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-gutter-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-scroll"
tabindex=
"-1"
><div
class=
"CodeMirror-sizer"
style=
"margin-left: 27px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"
><div
style=
"position: relative; top: 0px;"
><div
class=
"CodeMirror-lines"
role=
"presentation"
><div
role=
"presentation"
style=
"position: relative; outline: none;"
><div
class=
"CodeMirror-measure"
><pre><span>
xxxxxxxxxx
</span></pre><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
><div>
9
</div></div></div><div
class=
"CodeMirror-measure"
></div><div
style=
"position: relative; z-index: 1;"
></div><div
class=
"CodeMirror-code"
role=
"presentation"
style=
""
><div
class=
"CodeMirror-activeline"
style=
"position: relative;"
><div
class=
"CodeMirror-activeline-background CodeMirror-linebackground"
></div><div
class=
"CodeMirror-gutter-background CodeMirror-activeline-gutter"
style=
"left: -27px; width: 27px;"
></div><div
class=
"CodeMirror-gutter-wrapper CodeMirror-activeline-gutter"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
1
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Accept-Ranges: bytes
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
2
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Content-Disposition: inline;filename="TestVideo.mp4"
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
3
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Content-Length: 23508699
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
4
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Content-Range: bytes 0-23508698/23508699
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
5
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Content-Type: video/mp4
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
6
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Date: Thu, 27 Jun 2019 01:52:35 GMT
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
7
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
ETag: TestVideo.mp4
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
8
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Expires: Thu, 04 Jul 2019 01:52:35 GMT
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
9
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Last-Modified: Fri, 15 Mar 2019 08:44:44 GMT
</span></pre></div></div></div></div></div></div><div
style=
"position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 234px;"
></div><div
class=
"CodeMirror-gutters"
style=
"height: 234px;"
><div
class=
"CodeMirror-gutter CodeMirror-linenumbers"
style=
"width: 26px;"
></div></div></div></div></pre><ul><li><p><span>
在这里浏览器判断服务器支不支持范围请求(断点续传)主要是看
</span><code>
Response Headers
</code><span>
是否有
</span><code>
Accept-Ranges
</code><span>
信息,且值不为
</span><code>
none
</code><span>
(
</span><code>
Accept-Ranges
</code><strong><span>
为禁止修改的HTTP头默认值为:bytes
</span></strong><span>
),因此要实现断点续传功能首先服务器要在
</span><code>
Response Headers
</code><span>
返回
</span><code>
Accept-Ranges: bytes
</code><span>
告诉客户端服务端支持断点续传。
</span></p></li><li><p><span>
其中
</span><code>
Content-Type
</code><span>
、
</span><code>
Accept-Ranges
</code><span>
、
</span><code>
Content-Disposition
</code><span>
、
</span><code>
Content-Length
</code><span>
为文件有效信息:
</span></p><ul><li><code>
Content-Type: video/mp4
</code><span>
:文件类型为MP4
</span></li><li><code>
Content-Disposition: inline;filename=
"
TestVideo.mp4
"
</code><span>
:以内联方式处理比特流、且文件名为TestVideo.mp4
</span></li><li><code>
Content-Length: 23508699
</code><span>
:当前请求将返回的文件比特流大小
</span></li><li><code>
Content-Range: bytes 0-23508698/23508699
</code><span>
:当前请求将返回文件完整的比特范围,这里是返回完整文件
</span></li></ul></li><li><p><span>
经测试发现,Chrome浏览器及BitComet下载器在获取文件前都会做一次这样的简单GET请求来判断服务器是否支持范。
</span><strong><span>
但是,值得注意的是,客户端并不会完整的接收完本次简单请求的比特流数据,而是在解析请求头中
</span><code>
Accept-Ranges
</code><span>
是否存在且值是否为
</span><code>
bytes
</code><span>
后马上主动断开连接,之后再根据客户端的设置进行范围请求,因此服务端无法悉知每一个过来的请求是获取完整文件还是仅仅为了识别服务器是否支持断点续传。
</span></strong></p></li></ul></li><li><p><span>
经过一次简单GET请求后,客户端根据
</span><code>
Response Headers
</code><span>
的
</span><code>
Accept-Ranges
</code><span>
知道服务端是否支持断点续传后会马上创建一个或多个GET请求,
</span><strong><span>
但这些GET请求与第一次GET请求在
</span><code>
Requset Headers
</code><span>
有不同,并且服务端返回206状态
</span></strong><span>
:
</span></p><p><span>
General:
</span></p><pre
spellcheck=
"false"
class=
"md-fences md-end-block md-fences-with-lineno ty-contain-cm modeLoaded"
lang=
"html"
><div
class=
"CodeMirror cm-s-inner CodeMirror-wrap"
lang=
"html"
><div
style=
"overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 31px;"
><textarea
autocorrect=
"off"
autocapitalize=
"off"
spellcheck=
"false"
tabindex=
"0"
style=
"position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"
></textarea></div><div
class=
"CodeMirror-scrollbar-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-gutter-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-scroll"
tabindex=
"-1"
><div
class=
"CodeMirror-sizer"
style=
"margin-left: 27px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"
><div
style=
"position: relative; top: 0px;"
><div
class=
"CodeMirror-lines"
role=
"presentation"
><div
role=
"presentation"
style=
"position: relative; outline: none;"
><div
class=
"CodeMirror-measure"
><pre><span>
xxxxxxxxxx
</span></pre><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
><div>
5
</div></div></div><div
class=
"CodeMirror-measure"
></div><div
style=
"position: relative; z-index: 1;"
></div><div
class=
"CodeMirror-code"
role=
"presentation"
style=
""
><div
class=
"CodeMirror-activeline"
style=
"position: relative;"
><div
class=
"CodeMirror-activeline-background CodeMirror-linebackground"
></div><div
class=
"CodeMirror-gutter-background CodeMirror-activeline-gutter"
style=
"left: -27px; width: 27px;"
></div><div
class=
"CodeMirror-gutter-wrapper CodeMirror-activeline-gutter"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
1
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Request URL: http://localhost:20003/rangeTest
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
2
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Request Method: GET
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
3
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Status Code: 206
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
4
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Remote Address: [::1]:20003
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
5
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Referrer Policy: no-referrer-when-downgrade
</span></pre></div></div></div></div></div></div><div
style=
"position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 130px;"
></div><div
class=
"CodeMirror-gutters"
style=
"height: 130px;"
><div
class=
"CodeMirror-gutter CodeMirror-linenumbers"
style=
"width: 26px;"
></div></div></div></div></pre><p><span>
Requset Headers:
</span></p><pre
spellcheck=
"false"
class=
"md-fences md-end-block md-fences-with-lineno ty-contain-cm modeLoaded"
lang=
""
><div
class=
"CodeMirror cm-s-inner CodeMirror-wrap"
lang=
""
><div
style=
"overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 31px;"
><textarea
autocorrect=
"off"
autocapitalize=
"off"
spellcheck=
"false"
tabindex=
"0"
style=
"position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"
></textarea></div><div
class=
"CodeMirror-scrollbar-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-gutter-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-scroll"
tabindex=
"-1"
><div
class=
"CodeMirror-sizer"
style=
"margin-left: 27px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"
><div
style=
"position: relative; top: 0px;"
><div
class=
"CodeMirror-lines"
role=
"presentation"
><div
role=
"presentation"
style=
"position: relative; outline: none;"
><div
class=
"CodeMirror-measure"
><pre><span>
xxxxxxxxxx
</span></pre><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
><div>
5
</div></div></div><div
class=
"CodeMirror-measure"
></div><div
style=
"position: relative; z-index: 1;"
></div><div
class=
"CodeMirror-code"
role=
"presentation"
style=
""
><div
class=
"CodeMirror-activeline"
style=
"position: relative;"
><div
class=
"CodeMirror-activeline-background CodeMirror-linebackground"
></div><div
class=
"CodeMirror-gutter-background CodeMirror-activeline-gutter"
style=
"left: -27px; width: 27px;"
></div><div
class=
"CodeMirror-gutter-wrapper CodeMirror-activeline-gutter"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
1
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Accept-Encoding: identity;q=1, *;q=0
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
2
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
DNT: 1
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
3
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Range: bytes=0-
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
4
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Referer: http://localhost:20003/rangeTest
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
5
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
</span></pre></div></div></div></div></div></div><div
style=
"position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 156px;"
></div><div
class=
"CodeMirror-gutters"
style=
"height: 156px;"
><div
class=
"CodeMirror-gutter CodeMirror-linenumbers"
style=
"width: 26px;"
></div></div></div></div></pre><p><span>
Response Headers:
</span></p><pre
spellcheck=
"false"
class=
"md-fences md-end-block md-fences-with-lineno ty-contain-cm modeLoaded"
lang=
""
><div
class=
"CodeMirror cm-s-inner CodeMirror-wrap"
lang=
""
><div
style=
"overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 31px;"
><textarea
autocorrect=
"off"
autocapitalize=
"off"
spellcheck=
"false"
tabindex=
"0"
style=
"position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"
></textarea></div><div
class=
"CodeMirror-scrollbar-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-gutter-filler"
cm-not-content=
"true"
></div><div
class=
"CodeMirror-scroll"
tabindex=
"-1"
><div
class=
"CodeMirror-sizer"
style=
"margin-left: 27px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"
><div
style=
"position: relative; top: 0px;"
><div
class=
"CodeMirror-lines"
role=
"presentation"
><div
role=
"presentation"
style=
"position: relative; outline: none;"
><div
class=
"CodeMirror-measure"
><pre><span>
xxxxxxxxxx
</span></pre><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
><div>
9
</div></div></div><div
class=
"CodeMirror-measure"
></div><div
style=
"position: relative; z-index: 1;"
></div><div
class=
"CodeMirror-code"
role=
"presentation"
style=
""
><div
class=
"CodeMirror-activeline"
style=
"position: relative;"
><div
class=
"CodeMirror-activeline-background CodeMirror-linebackground"
></div><div
class=
"CodeMirror-gutter-background CodeMirror-activeline-gutter"
style=
"left: -27px; width: 27px;"
></div><div
class=
"CodeMirror-gutter-wrapper CodeMirror-activeline-gutter"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
1
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Accept-Ranges: bytes
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
2
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Content-Disposition: inline;filename="TestVideo.mp4"
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
3
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Content-Length: 23508699
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
4
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Content-Range: bytes 0-23508698/23508699
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
5
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Content-Type: video/mp4
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
6
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Date: Thu, 27 Jun 2019 01:52:35 GMT
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
7
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
ETag: TestVideo.mp4
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt"
style=
"left: 0px; width: 18px;"
>
8
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Expires: Thu, 04 Jul 2019 01:52:35 GMT
</span></pre></div><div
style=
"position: relative;"
><div
class=
"CodeMirror-gutter-wrapper"
style=
"left: -27px;"
><div
class=
"CodeMirror-linenumber CodeMirror-gutter-elt CodeMirror-linenumber-show"
style=
"left: 0px; width: 18px;"
>
9
</div></div><pre
class=
" CodeMirror-line "
role=
"presentation"
><span
role=
"presentation"
style=
"padding-right: 0.1px;"
>
Last-Modified: Fri, 15 Mar 2019 08:44:44 GMT
</span></pre></div></div></div></div></div></div><div
style=
"position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 234px;"
></div><div
class=
"CodeMirror-gutters"
style=
"height: 234px;"
><div
class=
"CodeMirror-gutter CodeMirror-linenumbers"
style=
"width: 26px;"
></div></div></div></div></pre></li><li><p><span>
根据以上请求头,关键点在于
</span><code>
Range
</code><span>
,该字段告诉服务端此次请求应该返回文件的比特流范围(
</span><code>
bytes=0-
</code><span>
表示从0开始直至文件比特数组下标结束,也就是完整文件,
</span><a
href=
'https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Range'
><span>
详见
</span></a><span>
)。
</span></p></li><li><p><span>
此时服务端应在解析完
</span><code>
Range: bytes=0-
</code><span>
后获取对应的文件比特流信息返回给客户端,并且响应状态为
</span><a
href=
'https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/206'
><span>
206
</span></a><span>
,假如所请求的范围不合法,那么服务器应响应状态
</span><a
href=
'https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/416'
><span>
416
</span></a><span>
。
</span></p></li><li><p><span>
若请求的范围合法,服务端应获取对应文件片段(也可能是完整文件),设置请求头
</span><code>
Content-Range
</code><span>
、
</span><code>
Content-Length
</code><span>
、
</span><code>
Content-Type
</code><span>
等头信息后返回比特流给客户端。
</span></p></li><li><p><span>
至此,一个基于
</span><code>
HTTP1.1
</code><span>
协议的范围请求(断点续传)结束了。
</span></p></li></ul></li></ul><h4><a
name=
"%E4%B8%9A%E5%8A%A1%E9%80%BB%E8%BE%91%E8%AF%B4%E6%98%8E%EF%BC%9A"
class=
"md-header-anchor"
></a><span>
业务逻辑说明:
</span></h4><ol
start=
''
><li><p><span>
所有文件下载接口进来应先解析请求中的参数,从数据库获取
</span><code>
FileInfo
</code><span>
(含有文件大小、Hash值及FastDFS路径信息)及
</span><code>
UserFileInfo
</code><span>
(含有文件名)的信息:
</span></p><ul><li><strong><span>
若文件不存在则直接抛出
</span><code>
ResponseStatusException
</code><span>
异常,并设置
</span><code>
HttpStatus.NOT_FOUND
</code><span>
!
</span></strong></li></ul></li><li><p><span>
解析
</span><code>
Requset Headers
</code><span>
中的
</span><code>
Accept
</code><span>
、
</span><code>
Range
</code><span>
等信息:
</span></p><ul><li><span>
若
</span><code>
Range
</code><span>
不为空则调用
</span><code>
GenerateStorageClient.downloadFile
</code><span>
下载文件片段接口获取
</span><strong><span>
文件片段比特流
</span></strong><span>
,并且设置响应状态为
</span><a
href=
'https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/206'
><span>
206
</span></a></li><li><strong><span>
若
</span><code>
Range
</code><span>
不为空且范围不合法则直接抛出
</span><code>
ResponseStatusException
</code><span>
异常,并设置
</span><code>
HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE
</code><span>
!
</span></strong></li><li><span>
若
</span><code>
Range
</code><span>
为空则调用
</span><code>
GenerateStorageClient.downloadFile
</code><span>
下载文件片段接口获取
</span><strong><span>
完整文件比特流
</span></strong><span>
,并且设置响应状态为
</span><a
href=
'https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/200'
><span>
200
</span></a></li></ul></li><li><p><span>
根据
</span><code>
Requset Headers
</code><span>
中的
</span><code>
Range
</code><span>
设置
</span><code>
Response Headers
</code></p></li><li><p><span>
根据
</span><code>
Requset Headers
</code><span>
中的
</span><code>
Accept
</code><span>
设置
</span><code>
Response Headers
</code><span>
的
</span><code>
Content-Disposition
</code><span>
值(
</span><a
href=
'https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition'
><span>
详见
</span></a><span>
)
</span></p></li><li><p><span>
最后设置
</span><code>
Content-Length
</code><span>
、
</span><code>
Content-Range
</code><span>
、
</span><code>
Content-Type
</code><span>
并返回客户端比特流,在这里有一点需要注意下:
</span></p><ul><li><span>
若客户端在服务端输出比特流未完成时主动断开,服务端会抛
</span><code>
java.io.IOException: 你的主机中的软件中止了一个已建立的连接。
</code><span>
异常信息,在这里我们统一捕获不处理,仅输出
</span><code>
warn
</code><span>
级别日志信息
</span></li></ul></li></ol><h4><a
name=
"%E6%B5%81%E7%A8%8B%E5%9B%BE%EF%BC%9A"
class=
"md-header-anchor"
></a><span>
流程图:
</span></h4><div
class=
"md-diagram-panel"
><svg
height=
"1106.6875"
version=
"1.1"
width=
"945.125"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
style=
"overflow: hidden; position: relative;"
viewBox=
"0 0 945.125 1106.6875"
preserveAspectRatio=
"xMidYMid meet"
><desc
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
Created with Raphaël 2.2.0
</desc><defs
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><path
stroke-linecap=
"round"
d=
"M5,0 0,2.5 5,5z"
id=
"raphael-marker-block"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><marker
id=
"raphael-marker-endblock33-objvgfyp"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-objani5k"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-obj44vrj"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-objfh192"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-objm1t33"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-objlajc4"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-objee36n"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-obj9p7ff"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-objea6ub"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-obj7ws79"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-objpo38c"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-obj3xkw2"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-obj88uaz"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-objqammh"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-objbwq7n"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker><marker
id=
"raphael-marker-endblock33-objxw9bb"
markerHeight=
"3"
markerWidth=
"3"
orient=
"auto"
refX=
"1.5"
refY=
"1.5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
><use
xlink:href=
"#raphael-marker-block"
transform=
"rotate(180 1.5 1.5) scale(0.6,0.6)"
stroke-width=
"1.6667"
fill=
"currentColor"
stroke=
"none"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></use></marker></defs><rect
x=
"0"
y=
"0"
width=
"92"
height=
"36"
rx=
"20"
ry=
"20"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"start"
transform=
"matrix(1,0,0,1,80.1719,36.0938)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"startt"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,80.1719,36.0938)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
客户端请求
</tspan></text><rect
x=
"0"
y=
"0"
width=
"106"
height=
"36"
rx=
"0"
ry=
"0"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"analyzeParams"
transform=
"matrix(1,0,0,1,73.1719,158.1875)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"analyzeParamst"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,73.1719,158.1875)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
解析请求参数
</tspan></text><rect
x=
"0"
y=
"0"
width=
"106"
height=
"36"
rx=
"0"
ry=
"0"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"getFileInfo"
transform=
"matrix(1,0,0,1,73.1719,280.2813)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"getFileInfot"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,73.1719,280.2813)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
获取文件信息
</tspan></text><path
fill=
"var(--bg-color)"
stroke=
"currentColor"
d=
"M43.125,21.5625L0,43.125L86.25,86.25L172.5,43.125L86.25,0L0,43.125"
stroke-width=
"3"
id=
"fileExist"
class=
"flowchart"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
transform=
"matrix(1,0,0,1,39.9219,377.25)"
></path><text
x=
"48.125"
y=
"43.125"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"fileExistt"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,39.9219,377.25)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
文件是否存在
</tspan></text><rect
x=
"0"
y=
"0"
width=
"132.46875"
height=
"36"
rx=
"0"
ry=
"0"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"analyzeRange"
transform=
"matrix(1,0,0,1,59.9375,549.5938)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"analyzeRanget"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,59.9375,549.5938)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
解析请求头Range
</tspan></text><path
fill=
"var(--bg-color)"
stroke=
"currentColor"
d=
"M47.71875,23.859375L0,47.71875L95.4375,95.4375L190.875,47.71875L95.4375,0L0,47.71875"
stroke-width=
"3"
id=
"rangeIsEnpty"
class=
"flowchart"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
transform=
"matrix(1,0,0,1,30.7344,641.9688)"
></path><text
x=
"52.71875"
y=
"47.71875"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"rangeIsEnptyt"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,30.7344,641.9688)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
Range是否为空
</tspan></text><rect
x=
"0"
y=
"0"
width=
"78"
height=
"36"
rx=
"0"
ry=
"0"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"getFile"
transform=
"matrix(1,0,0,1,87.1719,823.5)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"getFilet"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,87.1719,823.5)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
获取文件
</tspan></text><rect
x=
"0"
y=
"0"
width=
"240.34375"
height=
"36"
rx=
"0"
ry=
"0"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"return200"
transform=
"matrix(1,0,0,1,6,945.5938)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"return200t"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,6,945.5938)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
响应200状态并返回完整文件比特流
</tspan></text><rect
x=
"0"
y=
"0"
width=
"77"
height=
"36"
rx=
"20"
ry=
"20"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"end"
transform=
"matrix(1,0,0,1,87.6719,1067.6875)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"endt"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,87.6719,1067.6875)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
请求结束
</tspan></text><path
fill=
"var(--bg-color)"
stroke=
"currentColor"
d=
"M48.09375,24.046875L0,48.09375L96.1875,96.1875L192.375,48.09375L96.1875,0L0,48.09375"
stroke-width=
"3"
id=
"rangeIsValid"
class=
"flowchart"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
transform=
"matrix(1,0,0,1,301.5938,641.5938)"
></path><text
x=
"53.09375"
y=
"48.09375"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"rangeIsValidt"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,301.5938,641.5938)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
Range是否有效
</tspan></text><rect
x=
"0"
y=
"0"
width=
"106"
height=
"36"
rx=
"0"
ry=
"0"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"getFileFragment"
transform=
"matrix(1,0,0,1,344.7813,823.875)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"getFileFragmentt"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,344.7813,823.875)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
获取文件片段
</tspan></text><rect
x=
"0"
y=
"0"
width=
"240.34375"
height=
"36"
rx=
"0"
ry=
"0"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"return206"
transform=
"matrix(1,0,0,1,277.6094,945.9688)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"return206t"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,277.6094,945.9688)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
响应206状态并返回文件片段比特流
</tspan></text><rect
x=
"0"
y=
"0"
width=
"100.34375"
height=
"36"
rx=
"0"
ry=
"0"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"error416"
transform=
"matrix(1,0,0,1,619.9688,671.6875)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"error416t"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,619.9688,671.6875)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
抛出416异常
</tspan></text><rect
x=
"0"
y=
"0"
width=
"100.34375"
height=
"36"
rx=
"0"
ry=
"0"
fill=
"var(--bg-color)"
stroke=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
stroke-width=
"3"
class=
"flowchart"
id=
"error404"
transform=
"matrix(1,0,0,1,543.9688,402.375)"
></rect><text
x=
"10"
y=
"18"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
id=
"error404t"
class=
"flowchartt"
transform=
"matrix(1,0,0,1,543.9688,402.375)"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
抛出404异常
</tspan></text><path
fill=
"none"
stroke=
"currentColor"
d=
"M126.171875,72.09375C126.171875,72.09375,126.171875,135.96550977230072,126.171875,153.67994314664975"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objvgfyp)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><path
fill=
"none"
stroke=
"currentColor"
d=
"M126.171875,194.1875C126.171875,194.1875,126.171875,258.0592597723007,126.171875,275.77369314664975"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objani5k)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><path
fill=
"none"
stroke=
"currentColor"
d=
"M126.171875,316.28125C126.171875,316.28125,126.171875,358.63720016926527,126.171875,372.7420624814913"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-obj44vrj)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><path
fill=
"none"
stroke=
"currentColor"
d=
"M126.171875,463.5C126.171875,463.5,126.171875,527.3717597723007,126.171875,545.0861931466497"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objfh192)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><text
x=
"131.171875"
y=
"473.5"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
yes
</tspan></text><path
fill=
"none"
stroke=
"currentColor"
d=
"M212.421875,420.375C212.421875,420.375,499.8878315500915,420.375,539.4705462703678,420.375"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objm1t33)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><text
x=
"217.421875"
y=
"410.375"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
no
</tspan></text><path
fill=
"none"
stroke=
"currentColor"
d=
"M126.171875,585.59375C126.171875,585.59375,126.171875,624.1185654103756,126.171875,637.4743363778398"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objlajc4)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><path
fill=
"none"
stroke=
"currentColor"
d=
"M126.171875,737.40625C126.171875,737.40625,126.171875,801.2780097723007,126.171875,818.9924431466497"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objee36n)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><text
x=
"131.171875"
y=
"747.40625"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
yes
</tspan></text><path
fill=
"none"
stroke=
"currentColor"
d=
"M221.609375,689.6875C221.609375,689.6875,280.2109222970903,689.6875,297.09320398912314,689.6875"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-obj9p7ff)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><text
x=
"226.609375"
y=
"679.6875"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
no
</tspan></text><path
fill=
"none"
stroke=
"currentColor"
d=
"M126.171875,859.5C126.171875,859.5,126.171875,923.3717597723007,126.171875,941.0861931466497"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objea6ub)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><path
fill=
"none"
stroke=
"currentColor"
d=
"M126.171875,981.59375C126.171875,981.59375,126.171875,1045.4655097723007,126.171875,1063.1799431466497"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-obj7ws79)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><path
fill=
"none"
stroke=
"currentColor"
d=
"M397.78125,737.78125C397.78125,737.78125,397.78125,801.6530097723007,397.78125,819.3674431466497"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objpo38c)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><text
x=
"402.78125"
y=
"747.78125"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
yes
</tspan></text><path
fill=
"none"
stroke=
"currentColor"
d=
"M493.96875,689.6875C493.96875,689.6875,592.9842413663864,689.6875,615.4657860369771,689.6875"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-obj3xkw2)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><text
x=
"498.96875"
y=
"679.6875"
text-anchor=
"start"
font-family=
""Arial""
font-size=
"14px"
stroke=
"none"
fill=
"currentColor"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font-family: Arial; font-size: 14px;"
stroke-width=
"1"
><tspan
dy=
"5"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
>
no
</tspan></text><path
fill=
"none"
stroke=
"currentColor"
d=
"M397.78125,859.875C397.78125,859.875,397.78125,923.7467597723007,397.78125,941.4611931466497"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-obj88uaz)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><path
fill=
"none"
stroke=
"currentColor"
d=
"M397.78125,981.96875C397.78125,981.96875,397.78125,1042.6875,397.78125,1042.6875C397.78125,1042.6875,126.171875,1042.6875,126.171875,1042.6875C126.171875,1042.6875,126.171875,1055.9914712905884,126.171875,1063.189127633348"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objqammh)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><path
fill=
"none"
stroke=
"currentColor"
d=
"M670.140625,707.6875C670.140625,707.6875,670.140625,1042.6875,670.140625,1042.6875C670.140625,1042.6875,126.171875,1042.6875,126.171875,1042.6875C126.171875,1042.6875,126.171875,1055.9914712905884,126.171875,1063.189127633348"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objbwq7n)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path><path
fill=
"none"
stroke=
"currentColor"
d=
"M594.140625,438.375C594.140625,438.375,594.140625,683.6875,594.140625,683.6875C594.140625,683.6875,606.140625,689.6875,594.140625,695.6875C594.140625,695.6875,594.140625,1042.6875,594.140625,1042.6875C594.140625,1042.6875,126.171875,1042.6875,126.171875,1042.6875C126.171875,1042.6875,126.171875,1055.9914712905884,126.171875,1063.189127633348"
stroke-width=
"3"
marker-end=
"url(#raphael-marker-endblock33-objxw9bb)"
style=
"-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"
></path></svg></div></div>
</body>
</html>
\ No newline at end of file
Development/文件下载接口修改(断点续传).md
View file @
dbf35503
# 云存储
系统安全升级:
# 云存储
系统安全升级:
...
...
@@ -47,15 +47,15 @@
Response Headers:
```html
Accept-Ranges: bytes
Content-Disposition: inline;filename="TestVideo.mp4"
Content-Length: 23508699
Content-Range: bytes 0-23508698/23508699
Content-Type: video/mp4
Date: Thu, 27 Jun 2019 01:52:35 GMT
ETag: TestVideo.mp4
Expires: Thu, 04 Jul 2019 01:52:35 GMT
Last-Modified: Fri, 15 Mar 2019 08:44:44 GMT
Accept-Ranges: bytes
Content-Disposition: inline;filename="TestVideo.mp4"
Content-Length: 23508699
Content-Range: bytes 0-23508698/23508699
Content-Type: video/mp4
Date: Thu, 27 Jun 2019 01:52:35 GMT
ETag: TestVideo.mp4
Expires: Thu, 04 Jul 2019 01:52:35 GMT
Last-Modified: Fri, 15 Mar 2019 08:44:44 GMT
```
- 在这里浏览器判断服务器支不支持范围请求(断点续传)主要是看```Response Headers```是否有```Accept-Ranges```信息,且值不为```none```(```Accept-Ranges```**为禁止修改的HTTP头默认值为:bytes**),因此要实现断点续传功能首先服务器要在```Response Headers```返回```Accept-Ranges: bytes```告诉客户端服务端支持断点续传。
...
...
Plan/云存储第三阶段开发说明文档.md
View file @
dbf35503
# 云存储
第三阶段开发说明文档
# 云存储
第三阶段开发说明文档
...
...
@@ -14,16 +14,16 @@
### 准备阶段:
*
现有功能完善:
*
文件下载接口修改(修改文件下载重定向为非重定向,不在暴露FastDFS地址)
*
文件下载接口修改(修改文件下载重定向为非重定向,不在暴露FastDFS地址)
(通过java代码下载太慢,尝试通过对fastdfs地址进行加密,并修改fastdfs-nginx-module来解决地址暴露的问题)
*
完善文件hash比对机制
*
模块设计:
*
用户模块设计
*
文件管理模块设计
*
鉴权模块设计
*
网关、
鉴权模块设计
*
模块搭建:
*
用户模块搭建
*
文件管理模块搭建
*
鉴权模块搭建
*
网关、
鉴权模块搭建
### 开发阶段:
...
...
@@ -47,11 +47,18 @@
*
上传凭证(UploadToken)
*
下载凭证(DownloadToken)
*
管理凭证(AccessToken)
*
空间特性
*
以空间概念代替原本公私有文件的属性,配合凭证系统实现指定空间的私有、公共读、公共读写的特性
*
文件夹功能
*
用户可通过后台管理对指定空间下的文件夹进行管理
*
网关开发:
*
使用
```Spring Cloud Gateway```
替代现有
```Spring Cloud Zuul```
*
开发拦截器,用于对所有url进行调用其他模块服务进行鉴权
### 测试阶段:
### 测试
、对接
阶段:
*
存储系统接口测试
*
后台管理系统接口测试
*
存储系统接口测试
、对接
*
后台管理系统接口测试
、对接
---
...
...
@@ -64,46 +71,86 @@
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| ---------------------- | ------------------ | -------- | ------------------------------------------------------------ |
| 文件下载接口修改 | 5 | 兰平雄 | 修改文件下载重定向为非重定向,
<br
/>
不在暴露FastDFS地址,
<br
/>
并减少断点续传不必要的内存消耗 |
| 完善文件hash值比对机制 |
3
| 兰平雄 | |
| 完善文件hash值比对机制 |
5
| 兰平雄 | |
#### 模块设计:
| 工作内容
| 计划用时(工作日) | 人员安排 | 备注
|
| ----------------
| ------------------ | -------------- | ----
---------- |
| 用户模块设计
| 3 | 兰平雄、陈俊雄 | 含接口
业务逻辑 |
|
文件管理模块设计 | 5 | 兰平雄、陈俊雄 | 含接口
业务逻辑 |
|
鉴权模块设计 | 5 | 王德明 | 网关鉴权
|
| 工作内容
| 计划用时(工作日) | 人员安排 | 备注
|
| ----------------
-- | ------------------ | -------- |
---------- |
| 用户模块设计
| 4 | | 含
业务逻辑 |
|
用户模块设计 | 7 | | 含
业务逻辑 |
|
网关、鉴权模块设计 | 5 | | 网关鉴权
|
#### 模块搭建:
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| ---------------- | ------------------ | -------- | ---- |
| 用户模块搭建
| 2 | 兰平雄
| |
| 文件管理模块搭建
| 2 | 兰平雄
| |
|
鉴权模块搭建 | 2 | 王德明
| |
| 工作内容
| 计划用时(工作日) | 人员安排 | 备注 |
| ----------------
--
| ------------------ | -------- | ---- |
| 用户模块搭建
| 1 |
| |
| 文件管理模块搭建
| 1 |
| |
|
网关、鉴权模块搭建 | 1 |
| |
### 开发阶段:
####
后台管理系统
开发:
####
用户模块
开发:
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| ---------------- | ------------------ | -------- | ---- |
| 用户文件信息查看 | 3 | | |
| 用户文件操作 | 3 | | |
| 用户文件统计 | 4 | | |
| 用户信息修改 | 3 | | |
| 用户文件统计 | 3 | | |
| 用户文件操作 | 2 | | |
| 用户信息修改 | 2 | | |
| 用户注册 | 3 | | |
| 鉴权接口 | 4 | | |
#### 存储模块开发:
#### 存储系统开发:
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| ---------- | ------------------ | -------- | ---- |
| 凭证系统 | 4 | | |
| 空间特性 | 5 | | |
| 文件夹功能 | 5 | | |
| 鉴权接口 | 4 | | |
#### 网关、鉴权模块开发:
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| -------- | ------------------ | -------- | ---- |
| 凭证系统 | 7 | | |
| 转发规则 | 2 | | |
| 日志记录 | 4 | | |
### 测试阶段:
| 工作内容 | 计划用时(工作日) | 人员安排 | 备注 |
| -------------------------- | ------------------ | -------- | ---- |
| 存储系统接口测试、对接 | 5 | | |
| 后台管理系统接口测试、对接 | 5 | | |
---
## 技术栈:
| 名称 | 版本 |
| ------------------ | ------------------------------------------------ |
| Spring Boot | 2.0.4.RELEASE => 2.1.6(升级至官方稳定版本GA) |
| Spring Cloud | Finchley => Finchley.SR3(升级至官方稳定版本GA) |
| fastdfs-client | 1.26.6 |
| mybayis-plus | 3.1.0 |
| lombok | 1.18.2 |
| commons-lang3 | 3.8.1 |
| jackson-databind | 2.9.8 |
| commons-codec | 1.11 |
| springfox-swagger2 | 2.9.2 |
| jave-all-deps | 2.4.6 |
---
## 开发文档:
*
[
文件下载接口修改
](
http
://119.28.51.83/chenjunxiong/TCloud_Document/blob/master/Development/%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%E6%8E%A5%E5%8F%A3%E4%BF%AE%E6%94%B9%EF%BC%88%E6%96%AD%E7%82%B9%E7%BB%AD%E4%BC%A0%EF%BC%89.md](http://119.28.51.83/chenjunxiong/TCloud_Document/blob/master/Development/文件下载接口修改(断点续传).md
)
)
*
[
文件下载接口修改
](
http
s://test-storage.tlifang.com/storage/download?userFileId=1144452015156822018
)
Plan/云存储第三阶段模块说明文档.md
0 → 100644
View file @
dbf35503
# 云存储第三阶段模块说明文档
# 云存储第三阶段模块说明文档
[
TOC
]
------
## 文档概要:
### 新增模块:
*
用户模块(
```tdfs_user```
)
*
网关模块(
```tdfs_gateway```
)
*
授权模块(
```tdfs_auth```
)
### 修改模块:
*
存储模块(
```tdfs_storage```
)
*
新增空间特性
*
新增空间特性配置信息
*
新增基于空间的文件夹特性
*
修改数据库所有时间类型为
```timestamp```
(更快的索引速度,但需要注意服务器时间)
*
修改数据库名有
```tcloud_storage```
为
```tdfs_storage```
---
## 模块说明:
### 用户模块(```tdfs_user```):
#### 库信息:
```
mysql
CREATE DATABASE tdfs_user DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
```
#### 表信息:
*
用户信息(
```user_info```
):
| 字段名 | 字段类型 | 必填 | 默认值 | 备注 |
| ----------- | ------------ | ---- | ------ | -------------------------- |
| id | bigint | 是 | -1 | 用户Id |
| username | varchar(128) | 是 | ‘’ | 用户名 |
| email | varchar(128) | 是 | ‘’ | 邮箱,作为登录账号 |
| phone | varchar(128) | 是 | ‘’ | 手机号码 |
| country | varchar(64) | 是 | ‘’ | 国家代码 |
| province | varchar(64) | 是 | ‘’ | 省、州代码 |
| city | varchar(64) | 是 | ‘’ | 城市代码 |
| address | varchar(256) | 是 | ‘’ | 街道地址 |
| website | varchar(256) | 是 | ‘’ | 网站地址 |
| type | tinyint(4) | 是 | -1 | 用户类型:
<br
/>
个人、企业 |
| status | tinyint(4) | 是 | -1 | 状态 |
| create_time | timestamp | 是 | CURRENT_TIMESTAMP | 创建时间 |
| modify_time | timestamp | 是 | CURRENT_TIMESTAMP | 修改时间 |
-
用户密码(
```user_password```
):
| 字段名 | 字段类型 | 必填 | 默认值 | 备注 |
| ----------- | ------------ | ---- | ------ | -------- |
| id | bigint | 是 | -1 | 用户Id |
| password | varchar(128) | 是 | ‘’ | 密码 |
| create_time | timestamp | 是 | CURRENT_TIMESTAMP | 创建时间 |
| modify_time | timestamp | 是 | CURRENT_TIMESTAMP | 修改时间 |
*
用户凭据(
```user_credentials```
):
| 字段名 | 字段类型 | 必填 | 默认值 | 备注 |
| ----------- | ------------ | ---- | ------ | -------- |
| id | bigint | 是 | -1 | 凭据Id |
| user_id | bigint | 是 | -1 | 用户Id |
| access_key | varchar(128) | 是 | ‘’ | 访问key |
| secret_key | varchar(128) | 是 | ‘’ | 秘钥key |
| status | tinyint | 是 | -1 | 状态 |
| create_time | timestamp | 是 | CURRENT_TIMESTAMP | 创建时间 |
| modify_time | timestamp | 是 | CURRENT_TIMESTAMP | 修改时间 |
#### 负责业务:
-
用户注册
-
用户基本信息维护
-
用户凭据管理
-
操作日志查看
### 网关模块(```tdfs_gateway```):
#### 负责业务:
*
负载均衡
*
凭据生成
*
凭据验证
*
限流
### 存储模块(```tdfs_storage```):
#### 变动说明:
*
移除
```user_info```
表
*
修改
```user_file_info```
表:
*
去除
```is_public```
字段
*
新增
```bucket_id```
字段,用于描述该文件所属空间
*
新增
```folder_path_id```
字段,用于描述该文件所属文件夹
*
新增表:
*
空间信息表
```bucket_info```
*
文件夹信息表
```folder_path_info```
*
空间生命周期配置(
```bucket_life_cycle_setting```
)
#### 库信息:
```
mysql
CREATE DATABASE tdfs_storage DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
```
#### 表信息:
*
文件信息(
```file_info```
):
| 字段名 | 字段类型 | 必填 | 默认值 | 备注 |
| ----------- | ------------ | ---- | ---------- | ----------- |
| id | bigint | 是 | -1 | |
| size | bigint | 是 | -1 | 文件大小 |
| hash | varchar(64) | 是 | '' | 文件hash值 |
| group | varchar(32) | 是 | '' | FastDFS组别 |
| path | varchar(128) | 是 | '' | FastDFS路径 |
| status | tinyint(4) | 是 | -1 | 文件状态 |
| create_time | timestamp | 是 | CURRENT_TIMESTAMP | 创建时间 |
| modify_time | timestamp | 是 | CURRENT_TIMESTAMP | 修改时间 |
-
用户文件信息(
```user_file_info```
):
| 字段名 | 字段类型 | 必填 | 默认值 | 备注 |
| ------------ | ------------ | ---- | ------ | --------------------- |
| id | bigint | 是 | -1 | |
| custom_id | varchar(128) | 是 | -1 | 用户自定义文件Id |
| user_id | bigint | 是 | -1 | 用户Id |
| file_id | bigint | 是 | -1 | 文件Id |
| bucket_id | bigint | 是 | -1 | 空间Id |
| folder_id | bigint | 是 | -1 | 文件夹Id |
| file_format | varchar(256) | 是 | ‘’ | 文件类型(MIME type) |
| is_delete | tinyint(1) | 是 | -1 | 是否删除 |
| expired_time | timestamp | 是 | CURRENT_TIMESTAMP | 过期时间 |
| create_time | timestamp | 是 | CURRENT_TIMESTAMP | 创建时间 |
| modify_time | timestamp | 是 | CURRENT_TIMESTAMP | 修改时间 |
-
用户媒体文件信息(
```user_media_file_info```
):
| 字段名 | 字段类型 | 必填 | 默认值 | 备注 |
| ------------------------ | ------------ | ---- | ------ | ------------------------------------------------------------ |
| id | bigint | 是 | -1 | |
| user_file_info_id | bigint | 是 | -1 | 用户文件Id |
| source_user_file_info_id | bigint | 是 | -1 | 原文件user_file_info主键,
<br
/>
若本条记录为原文件,
<br
/>
该字段与user_file_info_id相同 |
| type | varchar(64) | 是 | ‘’ | 多媒体文件类型:
<br
/>
video(视频文件)
<br
/>
audio(音频文件)
<br
/>
image(图片文件) |
| custom_info | varchar(256) | 是 | ‘’ | 自定义信息(可能为空):
<br
/>
当type为video、audio时,
<br
/>
该字段值为CustomMediaInfo对象Json字符串
<br
/>
当type为image时,
<br
/>
该字段值为CustomImageInfo对象Json字符串 |
| create_time | timestamp | 是 | CURRENT_TIMESTAMP | 创建时间 |
| modify_time | timestamp | 是 | CURRENT_TIMESTAMP | 修改时间 |
-
空间信息(
```bucket_info```
):
| 字段名 | 字段类型 | 必填 | 默认值 | 备注 |
| ----------- | ------------ | ---- | ------ | -------- |
| id | bigint | 是 | -1 | |
| user_id | bigint | 是 | -1 | 用户Id |
| name | varchar(128) | 是 | ‘’ | 空间名称 |
| is_public | tinyint(1) | 是 | -1 | 访问控制 |
| status | tinyint(1) | 是 | -1 | 状态 |
| create_time | timestamp | 是 | CURRENT_TIMESTAMP | 创建时间 |
| modify_time | timestamp | 是 | CURRENT_TIMESTAMP | 修改时间 |
*
空间生命周期配置(
```bucket_life_cycle_setting```
):
| 字段名 | 字段类型 | 必填 | 默认值 | 备注 |
| ----------- | ------------ | ---- | ------ | -------- |
| id | bigint | 是 | -1 | |
| bucket_id | bigint | 是 | -1 | 空间Id |
| name | varchar(128) | 是 | ‘’ | 空间名称 |
| type | tinyint(1) | 是 | -1 | 类型 |
| cycle | integer | 是 | -1 | 周期 |
| rule | varchar(128) | 是 | ‘’ | 匹配规则 |
| status | tinyint(1) | 是 | -1 | 状态 |
| create_time | timestamp | 是 | CURRENT_TIMESTAMP | 创建时间 |
| modify_time | timestamp | 是 | CURRENT_TIMESTAMP | 修改时间 |
*
文件夹信息(
```folder_info```
):
| 字段名 | 字段类型 | 必填 | 默认值 | 备注 |
| ----------- | ------------ | ---- | ------ | ------------ |
| id | bigint | 是 | -1 | |
| bucket_id | bigint | 是 | -1 | 空间Id |
| parent_id | bigint | 是 | -1 | 父级文件夹Id |
| name | varchar(128) | 是 | ‘’ | 文件夹名称 |
| path | text | 是 | ‘’ | 路径信息 |
| create_time | timestamp | 是 | CURRENT_TIMESTAMP | 创建时间 |
| modify_time | timestamp | 是 | CURRENT_TIMESTAMP | 修改时间 |
---
## 客户端与服务简单交互示意图:
```
mermaid
sequenceDiagram
participant 客户端
participant 网关、鉴权
participant 服务
客户端->>网关、鉴权: 发送请求
网关、鉴权->>服务: 调用校验token接口
服务->>网关、鉴权: token是否有效
alt token无效
网关、鉴权-->>客户端: 异常信息
end
alt token有效
网关、鉴权->>服务: 放行请求
网关、鉴权->>客户端: 返回信息
end
```
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment