Skip to content

Commit 1342076

Browse files
committed
download hepers
1 parent 4190e5d commit 1342076

File tree

6 files changed

+166
-4
lines changed

6 files changed

+166
-4
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ authors = ["Chris Parmer <[email protected]>", "Alexandr Romanenko <waralex@gmail
44
version = "1.0.0"
55

66
[deps]
7+
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
78
CodecZlib = "944b1d66-785c-5afd-91f1-9de20f533193"
89
DashBase = "03207cf0-e2b3-4b91-9ca8-690cf0fb507e"
910
DashCoreComponents = "1b08a953-4be3-4667-9a23-9da06441d987"

src/Dash.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ include("resources/application.jl")
2525
include("handlers.jl")
2626
include("server.jl")
2727
include("init.jl")
28+
include("components_utils/_components_utils.jl")
2829

2930
@doc """
3031
module Dash
@@ -109,4 +110,4 @@ end
109110

110111

111112

112-
end # module
113+
end # module
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include("express.jl")

src/components_utils/express.jl

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import Base64
2+
export dcc_send_file, dcc_send_string, dcc_send_bytes
3+
"""
4+
dbc_send_file(path::AbstractString, filename = nothing; type = nothing)
5+
6+
Convert a file into the format expected by the Download component.
7+
8+
# Arguments
9+
- `path` - path to the file to be sent
10+
- `filename` - name of the file, if not provided the original filename is used
11+
- `type` - type of the file (optional, passed to Blob in the javascript layer)
12+
"""
13+
function dcc_send_file(path, filename = nothing; type = nothing)
14+
filename = isnothing(filename) ? basename(path) : filename
15+
return dcc_send_bytes(read(path), filename, type = type)
16+
end
17+
18+
"""
19+
dcc_send_bytes(src::AbstractVector{UInt8}, filename; type = nothing)
20+
dcc_send_bytes(src::Function, filename; type = nothing)
21+
22+
Convert vector of bytes into the format expected by the Download component.
23+
24+
# Examples
25+
26+
Sending binary content
27+
```julia
28+
file_data = read("path/to/file")
29+
callback!(app, Output("download", "data"), Input("download-btn", "n_clicks"), prevent_initial_call = true) do n_clicks
30+
return dcc_send_bytes(file_data, "filename.fl")
31+
end
32+
```
33+
34+
Sending `DataFrame` in `Arrow` format
35+
```julia
36+
using DataFrames, Arrow
37+
...
38+
df = DataFrame(...)
39+
callback!(app, Output("download", "data"), Input("download-btn", "n_clicks"), prevent_initial_call = true) do n_clicks
40+
return dcc_send_bytes("df.arr") do io
41+
Arrow.write(io, df)
42+
end
43+
end
44+
```
45+
"""
46+
function dcc_send_bytes(src::AbstractVector{UInt8}, filename; type = nothing)
47+
48+
return Dict(
49+
:content => Base64.base64encode(src),
50+
:filename => filename,
51+
:type => type,
52+
:base64 => true
53+
)
54+
end
55+
56+
function dcc_send_bytes(src::Function, filename; type = nothing)
57+
io = IOBuffer()
58+
src(io)
59+
return dcc_send_bytes(take!(io), filename, type = type)
60+
end
61+
62+
"""
63+
dcc_send_data(src::AbstractString, filename; type = nothing)
64+
dcc_send_data(src::Function, filename; type = nothing)
65+
66+
Convert string into the format expected by the Download component.
67+
`src` is a string or function that takes a single argument - io and writes data to it
68+
69+
# Examples
70+
71+
Sending string content
72+
```julia
73+
text_data = "this is the test"
74+
callback!(app, Output("download", "data"), Input("download-btn", "n_clicks"), prevent_initial_call = true) do n_clicks
75+
return dcc_send_string(text_data, "text.txt")
76+
end
77+
```
78+
79+
Sending `DataFrame` in `CSV` format
80+
```julia
81+
using DataFrames, CSV
82+
...
83+
df = DataFrame(...)
84+
callback!(app, Output("download", "data"), Input("download-btn", "n_clicks"), prevent_initial_call = true) do n_clicks
85+
return dcc_send_string("df.csv") do io
86+
CSV.write(io, df)
87+
end
88+
end
89+
```
90+
"""
91+
function dcc_send_string(src::AbstractString, filename; type = nothing)
92+
93+
return Dict(
94+
:content => src,
95+
:filename => filename,
96+
:type => type,
97+
:base64 => false
98+
)
99+
end
100+
101+
function dcc_send_string(src::Function, filename; type = nothing)
102+
io = IOBuffer()
103+
src(io)
104+
return dcc_send_string(String(take!(io)), filename, type = type)
105+
end

test/components_utils.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using Test
2+
using Dash
3+
using Base64
4+
@testset "Send String" begin
5+
data = "test string"
6+
res = dcc_send_string(data, "test_file.csv"; type = "text/csv")
7+
@test res[:content] == data
8+
@test res[:filename] == "test_file.csv"
9+
@test res[:type] == "text/csv"
10+
@test !res[:base64]
11+
12+
data2 = "test 2 string"
13+
res = dcc_send_string("test_file.csv"; type = "text/csv") do io
14+
write(io, data2)
15+
end
16+
@test res[:content] == data2
17+
@test res[:filename] == "test_file.csv"
18+
@test res[:type] == "text/csv"
19+
@test !res[:base64]
20+
end
21+
@testset "Send Bytes" begin
22+
data = "test string"
23+
res = dcc_send_bytes(Vector{UInt8}(data), "test_file.csv"; type = "text/csv")
24+
@test res[:content] == Base64.base64encode(data)
25+
@test res[:filename] == "test_file.csv"
26+
@test res[:type] == "text/csv"
27+
@test res[:base64]
28+
29+
data2 = "test 2 string"
30+
res = dcc_send_bytes("test_file.csv"; type = "text/csv") do io
31+
write(io, data2)
32+
end
33+
@test res[:content] == Base64.base64encode(data2)
34+
@test res[:filename] == "test_file.csv"
35+
@test res[:type] == "text/csv"
36+
@test res[:base64]
37+
end
38+
@testset "Send File" begin
39+
40+
file = "assets/test.png"
41+
res = dcc_send_file(file, nothing; type = "text/csv")
42+
@test res[:content] == Base64.base64encode(read(file))
43+
@test res[:filename] == "test.png"
44+
@test res[:type] == "text/csv"
45+
@test res[:base64]
46+
47+
file = "assets/test.png"
48+
res = dcc_send_file(file, "ttt.jpeg"; type = "text/csv")
49+
@test res[:content] == Base64.base64encode(read(file))
50+
@test res[:filename] == "ttt.jpeg"
51+
@test res[:type] == "text/csv"
52+
@test res[:base64]
53+
end

test/runtests.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include("env.jl")
1+
#=include("env.jl")
22
include("resources.jl")
33
include("devtools.jl")
44
include("dash_creation.jl")
@@ -8,5 +8,6 @@ include("utils.jl")
88
include("context.jl")
99
include("core.jl")
1010
include("misc.jl")
11-
include("callbacks.jl")
12-
#include("dev.jl")
11+
include("callbacks.jl")=#
12+
include("components_utils.jl")
13+
#include("dev.jl")

0 commit comments

Comments
 (0)