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
3102790f
Commit
3102790f
authored
Jun 28, 2019
by
chenjunxiong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First Commit
parent
5edbf066
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
421 additions
and
2 deletions
+421
-2
Development/文件下载接口修改(断点续传).html
+419
-0
Plan/云存储第三阶段开发说明文档.md
+2
-2
No files found.
Development/文件下载接口修改(断点续传).html
0 → 100644
View file @
3102790f
<!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
Plan/云存储第三阶段开发说明文档.md
View file @
3102790f
# 云存储
第三阶段开发说明文档
# 云存储
第三阶段开发说明文档
...
...
@@ -105,5 +105,5 @@
## 开发文档:
*
[
文件下载接口修改
](
)
*
[
文件下载接口修改
](
[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
)
)
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